spring cloud ribbon 負載均衡類1
Ribbon 在實現客戶端負載均衡時,是通過Ribbo的ILoadBalancer接口實現的。
AbstractLoadBalancer
是ILoadBalancer接口的抽象實現,定義了一個分組枚舉類ServerGroup
還實現了一個chooseServer()方法,其中key為null,表示在選擇具體實例時忽略key的條件判斷
還定義了兩個抽象方法
getServerList(ServerGroup serverGroup):根據分組類型獲取不同的實例列表
getLoadBalancerStats():定義了獲取LoadBalancerStats對象的方法,
LoadBalancerStats對象被用來存儲負載均衡中各個服務實例當前的屬性和統計信息。
BaseLoadBalancer
是Ribbon負載均衡的基礎實現類,
定義並維護了兩個存儲服務實例Server對象的列表。一個用於存儲所有服務實例的清單,
一個用於存儲正常服務的實例清單
定義了各服務實例屬性和統計信息的LoadBalancerStats對象
定義了檢查服務實例是否正常服務的IPing對象,默認為null,構造時註入
定義了檢查服務實例操作的執行策略對象IPingStrategy,在BaseLoadBalancer中
默認使用了SerialPingStrategy,遍歷檢查
定義了負載均衡的處理規則IRule對象,從BaseLoadBalancer中
chooseServer(Object key),實際將選擇任務委托給IRule.choose()方法,IRule默認為
RoundRobinRule
啟動ping任務:在BaseLoadBalancer的默認構造方法中,會直接啟動一個用於定時檢查Server是否健康的任務
DynamicServerListLoadBalancer<T>
對基礎負載均衡的擴展。在該負載均衡中,實現了服務實例清單在運行期的動態更新能力;
同時,還具備了對服務實例清單的過濾功能。新增如下
ServerList<T> serverListImpl
ServerList繼承結構如下
上圖中有多個ServerList的實現類,那麽在DynamiceServerListLoadBalancer中的ServerList默認配置到底使用了哪個具體實現?
既然該負載均衡類中需要實現服務實例的動態更新,那麽勢必需要Ribbon具備訪問Eureka來獲取服務實例的能力,在包
org.springframework.cloud.netflix.ribbon.eureka下,可以找到配置類EurekaRibbonClientConfiguration,找到如下
這裏創建的一個DomainExtractingServerList實例,在這個類源碼中,還定義類一個ServerList list. 同時對getInitialListOfServers()
和getUpdatedListOfServers()的具體實現,其實委托給內部定義的ServerList list對象
由構造方法傳入的DiscoveryEnabledNIWSServerLIst實現的。
在DiscoveryEnableNIWSServerList中
在obtainServersViaDiscovery()方法中
主要邏輯是,依靠EurekaClient從服務註冊中心獲取到具體的服務實例InstanceInfo列表,vipAddress可以理解為邏輯上的服務名如USER-SERVICE
然後遍歷,找到UP的實例轉換成DiscoveryEnabledServer對象 ,返回
返回的結果List到了DomainExtractingServerList類中,將繼續通過setZones()方法進行處理
ServerListUpdater
DynamicServerListLoadBalancer類中屬性ServerListUpdater中
主要是對ServerList的更新,
而ServerListUpdater的實現類不多,如下
PollingServerListUpdater:動態服務列表更新的默認策略,也就是DynamicServerListLoadBalancer中默認實現,
它通過定時任務實現更新
EurekaNotificationServerListUpdater 需要利用Eureka的事件監聽器來驅動服務列表的更新操作
ServerListFilter
回到updateAction.doUpdate()方法,在DynamicServerListLoadBalancer中,調用updateListOfServers()方法
調用之前提到的ServerList.getUpdatedListOfServers(),獲取到從Eureka Server中獲取服務可用實例的列表。
通過ServerListFilter filter過濾,繼承關系如下
AbstractServerListFilter:定義類過濾時需要的一個重要對象LoadBalancerStats,該對象存儲了一些屬性和統計信息等
ZoneAffinityServerListFilter:該過濾器基於“區域感知(Zone Affinity)”的方式實現服務實例的過濾,源碼
過濾後,通過shouldEnableZoneAffinity()方法來判斷是否啟用“區域感知”功能。
使用LoadBalancerStats.getZoneSnapshot()獲取過濾後同區域實例的基礎指標(包含實例數量,斷路器斷開數,活動請求數,實例平均負載等)
根據一系列的算法求出下面的幾個評價值並與設置的閾值進行比較,若有一個條件符合,就不啟用“區域感知”。
可以實現當集群出現區域故障時,依然可以依靠其他區域的實例進行正常服務的高可用保障。
blackOutServerPercentage:故障實例百分比(斷路器斷開數/實例數)>=0.8
activeRequestsPerServer:實例平均負載>=0.6
availableSevers: 可用實例數(實例數 - 斷路器斷開數)<2
DefaultNIWSServerListFilter 完全繼承ZoneAffinityServerListFilter,是默認NIWS(Netflix Internal Web Server)過濾器
ServerListSubSetFilter:
ZonePreferenceServerListFilter: Spring Cloud整合時新增的過濾器。若使用Spring Cloud整合Eureka和Ribbon時默認使用該過濾器
根據zone過濾出實例
spring cloud ribbon 負載均衡類1