Ribbon架構剖析

file

在學習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();
}

這個接口中保護了一個基本的負載均衡器所必須的全部功能:dom

  1. addServers(List)向負載均衡器中添加服務實例
  2. chooseServer(Object)根據負載均衡策略,從負載均衡器中挑選出一個服務實例
  3. markServerDown(Server)下線負載均衡器中的某個具體實例
  4. getReachableServers()返回當前可正常服務的實例列表
  5. getAllServers()返回全部的服務實例列表

接着來看一下這個接口的UML圖
file學習

首先看AbstractLoadBalancer這個類,這個類是ILoadBalancer接口的抽象類實現。
在這個抽象類中定義了一個表示服務實例狀態的枚舉的同時還新增了兩個抽象方法:url

public enum ServerGroup{
        ALL,
        STATUS_UP,
        STATUS_NOT_UP
    }
    public abstract List<Server> getServerList(ServerGroup serverGroup);
    public abstract LoadBalancerStats getLoadBalancerStats();
  1. getServerList(ServerGroup):根據分組類型來返回不一樣的服務實例列表。
  2. getLoadBalancerStats():返回LoadBalancerStatus對象,這個LoadBalancerStats對象是用來存儲負載均衡器中各個服務實例當前的屬性和統計信息的

AbstractLoadBalancer共有兩個實現類,右側的NoOpLoadBalancer是一個空的實現類,這裏能夠忽略不計。這裏接着繼續看BaseLoadBalancer線程

BaseLoadBalancer是負載均衡器的基礎實現類,這個類對於接口ILoadBalancer的全部方法都給予了基礎的實現,除此以外還保護了不少重要的對象code

兩個存儲當前服務實例對象的列表,一個是包含全部服務、一個是包含正常服務server

@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的實現類有如下幾種:

  1. PingUrl:使用HttpClient去get請求某個url,判斷其是否alive
  2. PingConstant:固定返回某服務是否可用,默認返回true
  3. NoOpPing:沒有任何操做,直接返回true
  4. DummyPing:一樣是直接返回true
  5. NIWSDiscoveryPing:根據服務的實例對象InstanceInfoInstanceStatus去判斷,若是爲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線性輪詢

除此以外的實現爲:

  1. BestAvailableRule:選擇最小請求數
  2. RandomRule:隨機選擇
  3. RetryRule:輪詢重試
  4. WeightedResponseTimeRule:根據響應時間分配權重
  5. ZoneAvoidanceRule:根據服務的分區可用性輪詢

如今繼續看BaseLoadBalancer的子類DynamicServerListLoadBalancer

這個類對基礎負載均衡器作了擴展。擴展的功能以下:

  1. 服務實例運行期間的動態更新
  2. 服務實例的過濾
服務列表
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();
}

它的實現類有兩個:

  1. PollingServerListUpdater:經過定時任務進行更新
  2. EurekaNotificationServerListUpdater:利用Eureka的事件監聽器來更新
服務列表過濾器
public interface ServerListFilter<T extends Server> {

    public List<T> getFilteredListOfServers(List<T> servers);

}

該接口主要用於根據一些規則過濾傳入的服務實例列表,該接口的實現類以下:

  1. ZoneAffinityServerListFilter:基於Eureka的分區規則對服務實例的過濾
  2. DefaultNIWSServerListFilterZoneAffinityServerListFilter的子類且沒有作特殊的更新
  3. ServerListSubsetFilter:經過比較服務實例的通訊失敗數和併發鏈接數來剔除那些相對不夠健康的實例
  4. ZonePreferenceServerListFilter:使用SpringCloud整合eureka和ribbon時默認使用的該過濾器。它實現了經過配置或eureka實例無數據的所屬區域(Zone)來過濾出同區域的服務實例

ZoneAwareLoadBalancer則是對DynamicServerListLoadBalancer的擴展,它主要增長了區域過濾的功能

原文地址

相關文章
相關標籤/搜索