概述
SpringCloud底層其實是利用了一個名為Ribbon的組件,來實現負載均衡功能的。
源碼
LoadBalancerInterceptor
其中含有intercept方法,攔截用戶的HttpRequest請求:
-
request.getURI()
獲取請求uri,即http://userservice/user/ -
originalUri.getHost()
獲取uir路徑的主機名,即服務id:userservice -
this.loadBalancer.execute()
處理服務id和用戶請求
其中loadBalancer類型為LoadBalancerClient,如下
LoadBalancerClient
execute()
- getLoadBalancer(serviceId):根據服務id獲取ILoadBalancer(負載均衡器),該ILoadBalancer會用serviceId去eureka獲取服務列表并保存
- getServer(loadBalancer):利用內置的負載均衡算法,從服務列表中選擇一個
- 隨后再訪問并跟蹤,就能獲得對應的 ip:port
IRule負載均衡策略
上述類中使用getServer進行負載均衡,該方法中實際上調用了ILoadBalancer(負載均衡器)的chooseServer方法,而該方法中則又調用了IRule.choose()方法;IRule類的默認新建對象是RoundRobinRule,即輪詢
總結
基本流程如下:
- 攔截我們的RestTemplate請求http://userservice/user/1
- RibbonLoadBalancerClient會從請求url中獲取服務名稱,也就是user-service
- DynamicServerListLoadBalancer根據user-service到eureka拉取服務列表
- eureka返回列表,localhost:8081、localhost:8082
- IRule利用內置負載均衡規則,從列表中選擇一個,例如localhost:8081
- RibbonLoadBalancerClient修改請求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,發起真實請求
負載均衡策略
Ribbon中自帶的負載均衡策略
負載均衡的規則定義在IRule接口中,IRule又有不同的實現類,實現不同的負載均衡策略
內置負載均衡規則類 | 規則描述 |
---|---|
RoundRobinRule | 簡單輪詢服務列表來選擇服務器。它是Ribbon默認的負載均衡規則。 |
AvailabilityFilteringRule | 對以下兩種服務器進行忽略: (1)在默認情況下,這臺服務器如果3次連接失敗,這臺服務器就會被設置為“短路”狀態。短路狀態將持續30秒,如果再次連接失敗,短路的持續時間就會幾何級地增加。 (2)并發數過高的服務器。如果一個服務器的并發連接數過高,配置了AvailabilityFilteringRule規則的客戶端也會將其忽略。并發連接數的上限,可以由客戶端的..ActiveConnectionsLimit屬性進行配置。 |
WeightedResponseTimeRule | 為每一個服務器賦予一個權重值。服務器響應時間越長,這個服務器的權重就越小。這個規則會隨機選擇服務器,這個權重值會影響服務器的選擇。 |
ZoneAvoidanceRule | 以區域可用的服務器為基礎進行服務器的選擇。使用Zone對服務器進行分類,這個Zone可以理解為一個機房、一個機架等。而后再對Zone內的多個服務做輪詢。 |
BestAvailableRule | 忽略那些短路的服務器,并選擇并發數較低的服務器。 |
RandomRule | 隨機選擇一個可用的服務器。 |
RetryRule | 重試機制的選擇邏輯 |
默認的實現就是ZoneAvoidanceRule,是一種輪詢方案
自定義負載均衡策略
在服務消費者的啟動類中定義新的IRule
@Bean
public IRule randomRule(){return new RandomRule();
}
并在對應service模塊的application.yml中添加新的配置
# 給某個微服務配置負載均衡規則,這里是userservice服務
userservice: ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 負載均衡規則
注意,一般用默認的負載均衡規則,不做修改。
饑餓加載
Ribbon默認采用懶加載,即第一次訪問時才會去創建LoadBalancerClient,請求時間比較長
饑餓加載會在項目啟動時創建,降低第一次訪問的耗時
開啟饑餓加載:
ribbon:eager-load:enabled: trueclients: userservice