負載均衡分用戶端負載均衡和服務端負載均衡,例如nginx,接收到請求之後,在通過負載均衡算法,選擇一個伺服器,而用戶端負載均衡則不同,是在發送請求之前,根據曆史的請求統計資料及相關政策選擇一個目标伺服器,後直接通路目标伺服器。服務端負載均衡即所有請求都要全局統籌,而用戶端負載均衡,則是每個服務各自維護自己負載均衡。
例如spring cloud中的ribbon,用戶端從Euraka中擷取到伺服器的執行個體清單,在發送請求前通過負載均衡算法從中選擇一個目标伺服器。
ribbon中比較核心的接口就是ILoadBalancer,IPing,IRule。

其中ILoadBalancer負責全局調用,其中的chooseServer,則是調用Rule的choose方法。
IPing判斷目标的服務能否通路,預設有以下幾種實作:
- PingUrl 真實的去ping 某個url,判斷其是否alive
- PingConstant 固定傳回某服務是否可用,預設傳回true,即可用
- NoOpPing 不去ping,直接傳回true,即可用。
- DummyPing 直接傳回true,并實作了initWithNiwsConfig方法。
- NIWSDiscoveryPing,根據DiscoveryEnabledServer的InstanceInfo的InstanceStatus去判斷,如果為InstanceStatus.UP,則為可用,否則不可用。
從baseLoadBalncer的源碼是中可以看到,Iping是在負載均衡ILoadBalancer初始化的時候,啟動一個定時任務,預設間隔10s執行ping任務,判斷服務是否可用。
而IRule則是具體的負載均衡政策,預設實作有以下幾種:
- BestAvailableRule 選擇最小請求數
- ClientConfigEnabledRoundRobinRule 輪詢
- RandomRule 随機選擇一個server
- RoundRobinRule 輪詢選擇server
- RetryRule 根據輪詢的方式重試
- WeightedResponseTimeRule 根據響應時間去配置設定一個weight ,weight越低,被選擇的可能性就越低
- ZoneAvoidanceRule 根據server的zone區域和可用性來輪詢選擇
說到負載均衡政策,還有一個比較重要的類是ServerStats,是統計一個服務的狀态,包括總的請求數,目前活動的請求activeRequestsCount(本用戶端調用的請求),上次請求時間等等,這些狀态是由Ribbon維護的一個目前用戶端的請求狀态,例如,當發起一個請求時,activeRequestsCount加1,當請求結束時,activeRequestsCount減1。
下面看一下BestAvailableRule的實作,就是簡單的周遊serverList的,剔除掉被tripped的服務執行個體後,從中選擇一個activeRequestsCount最小的服務。