一、首先第一步,搭建eureka-server (注冊中心服務端),這是一個獨立的微服務
1、在微服務的父工程下,新建一個maven項目作為eureka服務端的項目
2、在項目中的pom文件中引入eureka服務端的依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
3、編寫啟動類,注意啟動類上要加上@EnableEurekaServer注解,開啟eureka的注冊中心功能
@SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
4、在application.yml配置文件中書寫配置
包括:配置服務端口號、配置服務名稱、配置eureka的地址信息(eureka自己也是一個微服務,他會把自己也注冊到eureka中)
server:
port: 10086
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
5、接下來就可以啟動項目啦,到瀏覽器中訪問地址 http://127.0.0.1:10086 出現eureka的圖形界面就成功了
二、服務注冊(將拆分的所有微服務注冊到eureka中,讓eureka來進行管理)
1、引入客戶端依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2、編寫application.yml配置文件
配置信息包括:同樣包括三個基本的配置: 服務端口、服務名稱、服務地址信息
spring:
application:
name: userservice
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
三、服務拉取和負載均衡
之前我們服務調用服務是這么做的,服務請求地址是寫死的,這樣一個服務有多個實例的話就無法實現負載均衡了
@Resource private RestTemplate restTemplate; @GetMapping("{orderId}") public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) { // 根據id查詢訂單並返回
Order order = orderService.queryOrderById(orderId); //定義請求的路徑
String url = "http://127.0.0.1:8081/user/"+order.getUserId(); //發送get請求
User user = restTemplate.getForObject(url, User.class); order.setUser(user); return order; }
現在我們將請求地址進行如下改寫,用服務名稱代替IP地址和端口號
String url = "http://userservice/user/"+order.getUserId();
服務提供者如果有多個實例的話,還需要實現負載均衡,在restTemplate組件上添加一個 @LoadBalanced 注解即可實現
完成此操作后,spring會自動幫助我們從eureka-server端,根據userservice這個服務名稱,獲取實例列表,而后完成負載均衡。
@Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }
四、負載均衡的實現原理細節
1、問題:我們添加了@LoadBalanced注解,即可實現負載均衡功能,這是什么原理呢?
2、springcloud底層利用了一個名為Ribbon的組件來實現的負載均衡的功能
3、源碼跟蹤:核心類
5、基本流程如下:( 這里模擬訂單服務需要請求用戶服務 )
-
攔截我們的RestTemplate請求http://userservice/user/1
-
RibbonLoadBalancerClient會從請求url中獲取服務名稱,也就是userservice
-
DynamicServerListLoadBalancer根據userservice到eureka拉取服務列表
-
eureka返回列表,localhost:8081、localhost:8082
-
IRule利用內置負載均衡規則,從列表中選擇一個,例如localhost:8081
-
RibbonLoadBalancerClient修改請求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,發起真實請求
6、上面提到一個負載均衡規則概念:那到底有哪些負載均衡的規則呢,如何實現的呢?我們可以自定義規則嗎?
負載均衡的規則都定義在IRule接口中,而IRule有很多不同的實現類:
6.1 不同規則的含義如下所示:
規則描述 | |
---|---|
RoundRobinRule | 簡單輪詢服務列表來選擇服務器。它是Ribbon默認的負載均衡規則。 |
AvailabilityFilteringRule | 對以下兩種服務器進行忽略: (1)在默認情況下,這台服務器如果3次連接失敗,這台服務器就會被設置為“短路”狀態。短路狀態將持續30秒,如果再次連接失敗,短路的持續時間就會幾何級地增加。 (2)並發數過高的服務器。如果一個服務器的並發連接數過高,配置了AvailabilityFilteringRule規則的客戶端也會將其忽略。並發連接數的上限,可以由客戶端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit屬性進行配置。 |
WeightedResponseTimeRule | 為每一個服務器賦予一個權重值。服務器響應時間越長,這個服務器的權重就越小。這個規則會隨機選擇服務器,這個權重值會影響服務器的選擇。 |
ZoneAvoidanceRule (默認的) |
以區域可用的服務器為基礎進行服務器的選擇。使用Zone對服務器進行分類,這個Zone可以理解為一個機房、一個機架等。而后再對Zone內的多個服務做輪詢。 |
BestAvailableRule | 忽略那些短路的服務器,並選擇並發數較低的服務器。 |
RandomRule | 隨機選擇一個可用的服務器。 |
RetryRule | 重試機制的選擇邏輯 |
6.2 自定義負載均衡策略
通過定義IRule實現可以修改負載均衡的規則,有兩種方式:
方式一:在配置類中注冊一個IRule組件,注冊需要的規則,這種規則全局生效
@Bean public IRule randomRule(){ return new RandomRule(); }
方式二: 在服務消費者的application.yml配置文件中添加如下配置:(具體針對某一個服務生效)
userservice: #給某個微服務配置負載均衡規則,這里是是服務名稱 ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #負載均衡規則,這里是隨機訪問
7、飢餓加載
Ribbon默認是采用懶加載,即第一次訪問時才會去創建LoadBalanceClient,請求時間會很長。
而飢餓加載則會在項目啟動時創建,降低第一次訪問的耗時,通過在服務消費者配置文件中添加下面配置開啟飢餓加載:
ribbon:
eager-load:
enabled: true
clients: userservice #服務提供者的服務名稱