Java SpringBoot整合SpringCloud
1. SpringCloud特點
SpringCloud
專注于為典型的用例和擴展機制提供良好的開箱即用體驗,以涵蓋其他情況:
- 分布式/版本化配置
- 服務注冊和發(fā)現(xiàn)
Eureka
- 路由
Zuul
- 服務到服務的呼叫
- 負載均衡
Ribbon
- 斷路器
Hystrix
- 分布式消息傳遞
2. 分布式系統(tǒng)的三個指標CAP
在介紹SpringCloud
默認使用的注冊中心前,先介紹分布式系統(tǒng)的三個指標,分別是:
Consistency:
一致性,在分布式系統(tǒng)中,更新操作執(zhí)行成功后所有的用戶的讀操作必須返回最新值;client寫入,server同步至整個系統(tǒng);Availability:
可用性,只要收到用戶的請求,在一定的時間內服務器就必須給出回應,回應的結果可以是成功或是失敗;Partition tolerance:
分區(qū)容錯,即區(qū)間通信可能失敗,在網(wǎng)絡中斷,消息丟失的情況下,仍對外提供服務;一般無法避免,可以認為CAP中的P總是成立
CAP
定律說的是,在一個分布式計算機系統(tǒng)中,一致性C,可用性A,分區(qū)容錯性P這三種保證無法同時得到滿足,最多滿足兩個:
放棄P:
為了避免分區(qū)容錯性問題的發(fā)生,一種做法是將所有與事務相關的數(shù)據(jù)都放在一臺服務器上,雖然不能保證100%系統(tǒng)不會出錯,但是不會碰到由分區(qū)帶來的負面效果,這樣的做法會嚴重影響系統(tǒng)的擴展性。
放棄A:
放棄可用性,一旦遇到分區(qū)容錯故障,受到影響的服務器需要等待一定的時間,因此會導致在等待期間系統(tǒng)無法對外提供服務。
放棄C:
這兒說的放棄一致性,并不是完全放棄數(shù)據(jù)的一致性,而是放棄數(shù)據(jù)的強一致性,而保留數(shù)據(jù)的最終一致性。以網(wǎng)絡購物為例,對只剩下一件庫存的商品,如果同時接受到了兩份訂單,那么較晚的訂單將被告知商品告罄。
文中部分CAP理論摘自: https://www.cnblogs.com/hxsyl/p/4381980.html
3. Eureka
基本介紹:
Eureka
是SpringCloud
官方推薦用于服務注冊和發(fā)現(xiàn),一個基于REST的服務
SpringBoot
實現(xiàn)了Netflix OSS
的集成,使用Eureka
的原因之一是因為其可以利用Spring Cloud Netflix
的其他組件:智能路由(Zuul)、客戶端負載均衡(Ribbon
)等
基本組成:
Eureka
由多個Instance
(服務實例)組成,分為Eureka Server
和Eureka Client
其中Eureka Client
又可細分為:Service Provider、Service Consumer
Eureka Server
:服務端,提供服務的注冊和發(fā)現(xiàn);Eureka Client
:客戶端
Service Provider
:服務提供方,將自身服務注冊到Eureka,讓消費方找到Service Consumer
:服務消費方,從Eureka獲取注冊服務列表,從而消費服務
Eureka和Zookeeper:
1)由CAP理論的角度來看
Zookeeper
:ZK保證CP,突出強一致性,但無法保證每次訪問服務可用性,比如ZK會出現(xiàn)這樣一種情況:當master節(jié)點因為網(wǎng)絡故障與其他節(jié)點失去聯(lián)系時,剩余節(jié)點會重新進行l(wèi)eader選舉,在ZK選舉leader期間整個ZK集群都是不可用的,這就導致了在選舉期間注冊服務癱瘓。在云部署的環(huán)境下,因網(wǎng)絡問題使得ZK集群失去master節(jié)點是較大概率會發(fā)生的事兒,雖然服務最終會恢復,但是漫長的選舉時間導致的注冊長期不可用是難以容忍的。
Eureka
:Eureka保證AP,Eureka在設計時就優(yōu)先保證可用性。對于Eureka中的節(jié)點,每個節(jié)點都是平等的,幾個節(jié)點掛掉也不會影響正常節(jié)點的工作,剩余的節(jié)點依然可以提供注冊和查詢服務。但Eureka不保證強一致性,即查到的信息可能不是最新的。此外Eureka還有一種自我保護機制,如果在15分鐘內超過85%的節(jié)點都沒有正常的心跳,那么Eureka就會認為客戶端和注冊中心出現(xiàn)了網(wǎng)絡故障,但會保證當前節(jié)點依然可用,不會像ZK導致整個注冊服務癱瘓。
2)由節(jié)點分工的角度來看
Zookeeper
:ZK集群中節(jié)點分為三類,承擔不同的任務
Leader
:事務請求唯一的調度者和處理者(除了查詢請求)Follower
:處理非事務請求,參與Leader選舉投票- Observer:處理非事務請求,但不參與Leader選舉投票
Eureka
:在Eureka
集群中每個節(jié)點都是平等的,每個節(jié)點扮演相同的角色,它們通過相互注冊的方式來感知對方的存在,當由注冊消息時,它們會同步給集群內的其他節(jié)點
4. SpringCloud Demo
Demo整體結構(父子項目)
api
:Bean、DTO、POJO等以及Service接口controller
:服務消費方,前端交互provider
:服務提供方,服務實現(xiàn)registry
:服務注冊中心
4.1 registry
1)pom.xml
關鍵點在于導入eureka服務端依賴
以及SpringCloud
依賴
<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-server --> <!-- eureka服務端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <version>2.2.5.RELEASE</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
2)application.properties
進行Eureka服務端的相關配置 spring.application.name=SpringCloudDemoRegistry # server端口,自己喜歡 server.port=8888 # Eureka Server服務url以及默認zone,結尾必須eureka eureka.client.service-url.defaultZone= http://127.0.0.1:8888/eureka/ # eureka的自我保護機制,k8s環(huán)境下建議false eureka.server.enable-self-preservation=false # false表示自己端就是注冊中心,我的功能就是維護服務實例,不需要從server獲取注冊的服務信息 eureka.client.fetch-registry=false # false表示不將自己注冊到Eureka Server eureka.client.register-with-eureka=false
3)EurekaregistryApplication
使用@EnableEurekaServer
激活相關配置,使registry
模塊作為注冊中心Server
@EnableEurekaServer //聲明為注冊中心服務端 @SpringBootApplication public class EurekaregistryApplication { public static void main(String[] args) { SpringApplication.run(EurekaregistryApplication.class, args); } }
4.2 api
1)entity
實體類以部門和用戶信息為例,由于演示使用了Lombok
省點代碼,用于實現(xiàn)基本的CRUD
Department.class
@Data @ToString @NoArgsConstructor @AllArgsConstructor public class Department { private Long id; private Integer dId; private String dName; private Date updateTime; }
UserInfo.class
@Data @ToString @NoArgsConstructor @AllArgsConstructor public class UserInfo { private Long id; private Integer uId; private Integer dId; private String uName; private String uPhone; @Email(message = "非法郵件格式") //Validator格式校驗 private String uEmail; private String uAddress; private Date updateTime; private Department department; }
2)UserService
UserService
為服務接口,聲明需要提供和消費的方法,寫了幾個簡單查詢
public interface UserService { /** * 判斷用戶是否存在,0為不存在,返回值與uId相等則存在 * @param uId * @return */ Integer userExist(Integer uId); /** * 獲取用戶個人基本信息 * @param uId * @return */ UserInfo getUserInfo(Integer uId); /** * 獲取用戶個人詳情信息 * @param uId * @return */ UserInfo getUserDetailsInfo(Integer uId); }
4.3 provider
1)pom.xml
關鍵點是引入eureka客戶端依賴
、openfeign依賴
、SpringCloud
依賴
<dependencies> <!-- Springboot的依賴省略... --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
2)application.properties
配置Eureka
、Mybatis
以及DataSource
數(shù)據(jù)源等信息
spring.application.name=SpringCloudDemoProvider # Server端口 server.port=9999 # Eureka服務url eureka.client.service-url.defaultZone= http://127.0.0.1:8888/eureka/ eureka.client.register-with-eureka=true eureka.client.fetch-registry=true # Mybatis mybatis.mapper-locations= classpath:com.maziyao.provider.mapper/*.xml mybatis.type-aliases-package= com.maziyao.common.entity # DataSource數(shù)據(jù)源配置 spring.datasource.type=com.zaxxer.hikari.HikariDataSource # DataSource spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/boot-demo?serverTimezone=UTC spring.datasource.username=root spring.datasource.password=root
3)EurekaproviderApplication
provider
啟動類使用@EnableEurekaClient
聲明為EurekaClient
客戶端,作為ServiceProvider
@EnableEurekaClient @SpringBootApplication @EnableAspectJAutoProxy @MapperScan("com.maziyao.provider.mapper") @ComponentScan(basePackages = { "com.maziyao.provider.rest", "com.maziyao.provider.redis", "com.maziyao.provider.service", "com.maziyao.provider.config" }) public class EurekaproviderApplication { public static void main(String[] args) { SpringApplication.run(EurekaproviderApplication.class, args); } }
4)service
UserServiceImpl
作為UserService
接口實現(xiàn)類,@Service
用于標注 業(yè)務層 組件
自動注入mapper
層的mapper
接口并調用,mapper的SQL語句下面就略了,很簡單
需要注意的是,對于 數(shù)據(jù)訪問層 組件mapper
,使用@Repository
進行標注
@Service("userService") public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public Integer userExist(Integer uId) { return userMapper.userExist(uId); } @Override public UserInfo getUserInfo(Integer uId) { return userMapper.getUserInfo(uId); } @Override public UserInfo getUserDetailsInfo(Integer uId) { return userMapper.getUserDetailsInfo(uId); } }
5)rest
重點是rest包下的UserServer
,要知道Eureka是一個基于REST的服務
使用@RestController
標注并聲明為userServer
,這個是SpringBoot
注解,用于標注 控制層 組件
@RestController("userServer") public class UserServer { public static final Logger logger = LoggerFactory.getLogger(UserServer.class); @Autowired private UserService userService; @ResponseBody @RequestMapping(value = "/exist",method = RequestMethod.GET) public Integer existUserByUid(@RequestParam("uId")Integer uId){ return userService.userExist(uId); } @ResponseBody @RequestMapping(value = "/userInfo",method = RequestMethod.GET) public UserInfo getUserInfo(@RequestParam("uId")Integer uId){ return userService.getUserInfo(uId); } @ResponseBody @RequestMapping(value="/userDetailsInfo",method = RequestMethod.GET) public UserInfo getUserDetailsInfo(@RequestParam("uId")Integer uId){ return userService.getUserDetailsInfo(uId); } }
4.4 consumer
1)pom.xml
在Controller
的pom.xml
中也需要導入EurekaClient
的依賴,對于Provider
和Controller
都為Client
<dependencies> <!-- SpringBoot依賴省略... --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.2.5.RELEASE</version> </dependency> </dependencies>
2)application.properties
在application.properties
中配置Eureka
相關信息
spring.application.name=springCloudDemoController # Server端口 server.port=8899 # 注冊中心url eureka.client.service-url.defaultZone= http://127.0.0.1:8888/eureka/ eureka.client.register-with-eureka=true eureka.client.fetch-registry=true
3)EurekacontrollerApplication
與Provider
的啟動類一致,聲明啟動類為Eureka
的客戶端
并使用@EnableFeignClients
開啟Feign
,聲明性的web服務客戶端
@EnableEurekaClient @EnableFeignClients @SpringBootApplication @EnableAspectJAutoProxy @ComponentScan({ "com.maziyao.controller.config", "com.maziyao.controller.controller", "com.maziyao.controller.rest" }) public class EurekacontrollerApplication { public static void main(String[] args) { SpringApplication.run(EurekacontrollerApplication.class, args); } }
4)rest
controller
作為前端交互層,即控制層,此處UserClient
聲明調用方法
使用@FeignClient
聲明服務提供方在application.properties
中配置的spring.application.name
以及綁定服務提供方對應rest
包下的UserServer
類的@RestController("userServer")
@FeignClient(name = "springCloudDemoProvider",contextId = "userServer") public interface UserClient { @ResponseBody @RequestMapping(value = "/exist",method = RequestMethod.GET) public Integer existUserByUid(@RequestParam("uId")Integer uId); @ResponseBody @RequestMapping(value = "/userInfo",method = RequestMethod.GET) public UserInfo getUserInfo(@RequestParam("uId")Integer uId); @ResponseBody @RequestMapping(value="/userDetailsInfo",method = RequestMethod.GET) public UserInfo getUserDetailsInfo(@RequestParam("uId")Integer uId); }
5)UserController
控制層,使用@RestController
標注,并注入UserClien
t進行調用
@RestController public class UserController { private static final Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired private UserClient userClient; @ResponseBody @RequestMapping(value = "/exist",method = RequestMethod.GET) public Integer existUserByUid(@RequestParam("uId") Integer uId){ return userClient.existUserByUid(uId); } @ResponseBody @RequestMapping(value = "/userInfo",method = RequestMethod.GET) public UserInfo getUserInfoByUid(@RequestParam("uId")Integer uId){ return userClient.getUserInfo(uId); } @ResponseBody @RequestMapping(value = "/userDetailsInfo",method = RequestMethod.GET) public UserInfo getUserDetailsInfoByUid(@RequestParam("uId")Integer uId){ return userClient.getUserDetailsInfo(uId); } }
4.5 POSTMAN一下
注意:最后記得mvn install
,需要先將registry
運行起來,再分別運行provider
和controller
啟動registry:
啟動provider:
啟動consumer:
result:
到此這篇關于Java-SpringBoot
整合SpringCloud
的文章就介紹到這了,更多相關SpringBoot
整合SpringCloud
內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java的Socket實現(xiàn)長連接以及數(shù)據(jù)的發(fā)送和接收方式
這篇文章主要介紹了Java的Socket實現(xiàn)長連接以及數(shù)據(jù)的發(fā)送和接收方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09GitLab+Jenkins+Maven+Tomcat?實現(xiàn)自動集成、打包、部署
本文主要介紹了GitLab?+?Jenkins?+?Maven?+?Tomcat?實現(xiàn)自動集成、打包、部署,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01