在學習Ribbon之前,先看一下這張圖,這張圖完美的把Ribbon的基礎架構給描述出來了
這張圖的核心是負載均衡管理器,圍繞著它的是外面的這5大功能點,咱們就從核心開始看然后再帶出來其他的功能
首先看一下負載均衡器的核心接口ILoadBalancer
public interface ILoadBalancer { public void addServers(List<Server> newServers); public Server chooseServer(Object key); public void markServerDown(Server server); public List<Server> getReachableServers(); public List<Server> getAllServers(); }
這個接口中保護了一個基本的負載均衡器所必須的所有功能:
- addServers(List)向負載均衡器中添加服務實例
- chooseServer(Object)根據負載均衡策略,從負載均衡器中挑選出一個服務實例
- markServerDown(Server)下線負載均衡器中的某個具體實例
- getReachableServers()返回當前可正常服務的實例列表
- getAllServers()返回所有的服務實例列表
接著來看一下這個接口的UML圖
首先看AbstractLoadBalancer這個類,這個類是ILoadBalancer接口的抽象類實現。在這個抽象類中定義了一個表示服務實例狀態的枚舉的同時還新增了兩個抽象方法:
public enum ServerGroup{ ALL, STATUS_UP, STATUS_NOT_UP } public abstract List<Server> getServerList(ServerGroup serverGroup); public abstract LoadBalancerStats getLoadBalancerStats();
- getServerList(ServerGroup):根據分組類型來返回不同的服務實例列表。
- getLoadBalancerStats():返回LoadBalancerStatus對象,這個LoadBalancerStats對象是用來存儲負載均衡器中各個服務實例當前的屬性和統計信息的
AbstractLoadBalancer共有兩個實現類,右側的NoOpLoadBalancer是一個空的實現類,這里可以忽略不計。這里接著繼續看BaseLoadBalancer
BaseLoadBalancer是負載均衡器的基礎實現類,這個類對于接口ILoadBalancer的所有方法都給予了基礎的實現,除此之外還保護了很多重要的對象
兩個存儲當前服務實例對象的列表,一個是包含所有服務、一個是包含正常服務
@Monitor(name = PREFIX + "AllServerList", type = DataSourceType.INFORMATIONAL) protected volatile List<Server> allServerList = Collections .synchronizedList(new ArrayList<Server>()); @Monitor(name = PREFIX + "UpServerList", type = DataSourceType.INFORMATIONAL) protected volatile List<Server> upServerList = Collections .synchronizedList(new ArrayList<Server>());
存儲負載系統器各服務實例屬性和統計信息的對象
protected LoadBalancerStats lbStats;
心跳檢測對象
protected IPing ping = null;
IPing是用來向服務發起心跳檢測的,通過心跳檢測來判斷該服務是否可用。IPing的實現類有以下幾種:
- PingUrl:使用HttpClient去get請求某個url,判斷其是否alive
- PingConstant:固定返回某服務是否可用,默認返回true
- NoOpPing:沒有任何操作,直接返回true
- DummyPing:同樣是直接返回true
- NIWSDiscoveryPing:根據服務的實例對象InstanceInfo的InstanceStatus去判斷,如果為InstanceStatus.UP,則為可用
心跳檢測策略對象IPingStrategy
private final static SerialPingStrategy DEFAULT_PING_STRATEGY = new SerialPingStrategy(); protected IPingStrategy pingStrategy = DEFAULT_PING_STRATEGY;
默認實現是線型輪詢
負載均衡策略對象
private final static IRule DEFAULT_RULE = new RoundRobinRule(); protected IRule rule = DEFAULT_RULE;
IRule是在選擇實例的時候的負載均衡策略對象,默認使用的是RoundRobinRule線性輪詢
除此之外的實現為:
- BestAvailableRule:選擇最小請求數
- RandomRule:隨機選擇
- RetryRule:輪詢重試
- WeightedResponseTimeRule:根據響應時間分配權重
- ZoneAvoidanceRule:根據服務的分區可用性輪詢
現在繼續看BaseLoadBalancer的子類DynamicServerListLoadBalancer
這個類對基礎負載均衡器做了擴展。擴展的功能如下:
- 服務實例運行期間的動態更新
- 服務實例的過濾
服務列表
public interface ServerList<T extends Server> { /** * 獲取初始化的服務列表 */ public List<T> getInitialListOfServers(); /** * 獲取更新后的服務列表 */ public List<T> getUpdatedListOfServers(); }
在DynamicServerListLoadBalancer中默認使用的服務列表實現類是DomainExtractingServerList,只不過該服務列表內部還定義了一個服務列表,這個服務列表的實現類則是DiscoveryEnabledNIWSServerList
這個最終的服務列表的數據來源則主要依靠EurekaClient從注冊中心獲取
服務列表更新
這個接口定義了一系列的對服務列表的更新操作
public interface ServerListUpdater { //內部接口 public interface UpdateAction { //實現對服務列表的更新操作 void doUpdate(); } //啟動服務更新器 void start(UpdateAction updateAction); //停止服務更新器 void stop(); //返回最近的更新時間戳 String getLastUpdate(); //返回上一次更新到現在的時間間隔(ms) long getDurationSinceLastUpdateMs(); //返回錯過的更新周期數 int getNumberMissedCycles(); //返回核心線程數 int getCoreThreads(); }
它的實現類有兩個:
- PollingServerListUpdater:通過定時任務進行更新
- EurekaNotificationServerListUpdater:利用Eureka的事件監聽器來更新
服務列表過濾器
public interface ServerListFilter<T extends Server> { public List<T> getFilteredListOfServers(List<T> servers); }
該接口主要用于根據一些規則過濾傳入的服務實例列表,該接口的實現類如下:
- ZoneAffinityServerListFilter:基于Eureka的分區規則對服務實例的過濾
- DefaultNIWSServerListFilter:ZoneAffinityServerListFilter的子類且沒有做特殊的更新
- ServerListSubsetFilter:通過比較服務實例的通信失敗數和并發連接數來剔除那些相對不夠健康的實例
- ZonePreferenceServerListFilter:使用SpringCloud整合eureka和ribbon時默認使用的該過濾器。它實現了通過配置或eureka實例無數據的所屬區域(Zone)來過濾出同區域的服務實例
ZoneAwareLoadBalancer則是對DynamicServerListLoadBalancer的擴展,它主要增加了區域過濾的功能
關注公眾號:http://mp.weixin.qq.com/mp/homepage?__biz=MzU5MDgzOTYzMw==&hid=3&sn=ee8e8ecbdc8d22253994debf927273f5&scene=18#wechat_redirect,查看更多Spring、SpringBoot、SpringCloud源碼解析系列文章