添加@LoadBalanced注解,即可實現(xiàn)負載均衡功能,這是什么原理
1.負載均衡原理
SpringCloud底層其實是利用了一個名為Ribbon的組件,來實現(xiàn)負載均衡功能的。
2.源碼跟蹤
為什么我們只輸入了service名稱就可以訪問了呢?之前還要獲取ip和端口。
顯然有人幫我們根據(jù)service名稱,獲取到了服務(wù)實例的ip和端口。它就是LoadBalancerInterceptor
,這個類會在對RestTemplate的請求進行攔截,然后從Eureka根據(jù)服務(wù)id獲取服務(wù)列表,隨后利用負載均衡算法得到真實的服務(wù)地址信息,替換服務(wù)id。
我們進行源碼跟蹤:
1)LoadBalancerIntercepor
可以看到這里的intercept方法,攔截了用戶的HttpRequest請求,然后做了幾件事:
-
request.getURI()
:獲取請求uri,本例中就是 http://user-service/user/8 -
originalUri.getHost()
:獲取uri路徑的主機名,其實就是服務(wù)id,user-service
-
this.loadBalancer.execute()
:處理服務(wù)id,和用戶請求。
這里的this.loadBalancer
是LoadBalancerClient
類型,我們繼續(xù)跟入。
2)LoadBalancerClient
繼續(xù)跟入execute方法:
代碼是這樣的:
- getLoadBalancer(serviceId):根據(jù)服務(wù)id獲取ILoadBalancer,而ILoadBalancer會拿著服務(wù)id去eureka中獲取服務(wù)列表并保存起來。
- getServer(loadBalancer):利用內(nèi)置的負載均衡算法,從服務(wù)列表中選擇一個。本例中,可以看到獲取了8082端口的服務(wù)
放行后,再次訪問并跟蹤,發(fā)現(xiàn)獲取的是8081:實現(xiàn)了負載均衡。
3)負載均衡策略IRule
在剛才的代碼中,可以看到獲取服務(wù)使通過一個getServer
方法來做負載均衡:
這里的rule默認值是一個RoundRobinRule
,看類的介紹:
就是輪詢的意思
4)總結(jié)
SpringCloudRibbon的底層采用了一個攔截器,攔截了RestTemplate發(fā)出的請求,對地址做了修改。用一幅圖來總結(jié)一下:
基本流程如下:
- 攔截我們的RestTemplate請求http://userservice/user/1
- RibbonLoadBalancerClient會從請求url中獲取服務(wù)名稱,也就是user-service
- DynamicServerListLoadBalancer根據(jù)user-service到eureka拉取服務(wù)列表
- eureka返回列表,localhost:8081、localhost:8082
- IRule利用內(nèi)置負載均衡規(guī)則,從列表中選擇一個,例如localhost:8081
- RibbonLoadBalancerClient修改請求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,發(fā)起真實請求
3.負載均衡策略
3.1.負載均衡策略
負載均衡的規(guī)則都定義在IRule接口中,而IRule有很多不同的實現(xiàn)類:
不同規(guī)則的含義如下:
內(nèi)置負載均衡規(guī)則類 | 規(guī)則描述 |
---|---|
RoundRobinRule | 簡單輪詢服務(wù)列表來選擇服務(wù)器。它是Ribbon默認的負載均衡規(guī)則。 |
AvailabilityFilteringRule | 對以下兩種服務(wù)器進行忽略: (1)在默認情況下,這臺服務(wù)器如果3次連接失敗,這臺服務(wù)器就會被設(shè)置為“短路”狀態(tài)。短路狀態(tài)將持續(xù)30秒,如果再次連接失敗,短路的持續(xù)時間就會幾何級地增加。 (2)并發(fā)數(shù)過高的服務(wù)器。如果一個服務(wù)器的并發(fā)連接數(shù)過高,配置了AvailabilityFilteringRule規(guī)則的客戶端也會將其忽略。并發(fā)連接數(shù)的上限,可以由客戶端的..ActiveConnectionsLimit屬性進行配置。 |
WeightedResponseTimeRule | 為每一個服務(wù)器賦予一個權(quán)重值。服務(wù)器響應(yīng)時間越長,這個服務(wù)器的權(quán)重就越小。這個規(guī)則會隨機選擇服務(wù)器,這個權(quán)重值會影響服務(wù)器的選擇。 |
ZoneAvoidanceRule | 以區(qū)域可用的服務(wù)器為基礎(chǔ)進行服務(wù)器的選擇。使用Zone對服務(wù)器進行分類,這個Zone可以理解為一個機房、一個機架等。而后再對Zone內(nèi)的多個服務(wù)做輪詢。 |
BestAvailableRule | 忽略那些短路的服務(wù)器,并選擇并發(fā)數(shù)較低的服務(wù)器。 |
RandomRule | 隨機選擇一個可用的服務(wù)器。 |
RetryRule | 重試機制的選擇邏輯 |
默認的實現(xiàn)就是ZoneAvoidanceRule,是一種輪詢方案
3.2.自定義負載均衡策略
通過定義IRule實現(xiàn)可以修改負載均衡規(guī)則,有兩種方式:
- 代碼方式:在order-service中的OrderApplication類中,定義一個新的IRule:
@Bean
public IRule randomRule(){
return new RandomRule();
}
- 配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改規(guī)則:
userservice: # 給某個微服務(wù)配置負載均衡規(guī)則,這里是userservice服務(wù)
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 負載均衡規(guī)則
注意,一般用默認的負載均衡規(guī)則,不做修改。
4.饑餓加載
Ribbon默認是采用懶加載,即第一次訪問時才會去創(chuàng)建LoadBalanceClient,請求時間會很長。文章來源:http://www.zghlxwxcb.cn/news/detail-729151.html
而饑餓加載則會在項目啟動時創(chuàng)建,降低第一次訪問的耗時,通過下面配置開啟饑餓加載:文章來源地址http://www.zghlxwxcb.cn/news/detail-729151.html
ribbon:
eager-load:
enabled: true
clients: userservice
到了這里,關(guān)于【Java】微服務(wù)——Ribbon負載均衡(跟進源碼分析原理)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!