Spring Cloud中負載均衡器概覽

在上篇文章中(RestTemplate的逆襲之路,從發送請求到負載均衡)咱們完整的分析了RestTemplate的工做過程,在分析的過程當中,咱們遇到過一個ILoadBalancer接口,這個接口中有一個chooseServer方法是咱們選擇服務實例的方法,這個也是整個負載均衡中最最核心的部分,那麼它究竟是採用了什麼樣的策略從服務提供者列表中選出了一個服務供服務消費者去調用的?這是咱們今天要討論的問題,本文我主要是想基於互聯網上公開的資料,來對Spring Cloud中提供的負載均衡器作一個簡明扼要的介紹。java


本文是Spring Cloud系列的第八篇文章,瞭解前七篇文章內容有助於更好的理解本文:後端

1.使用Spring Cloud搭建服務註冊中心
2.使用Spring Cloud搭建高可用服務註冊中心
3.Spring Cloud中服務的發現與消費
4.Eureka中的核心概念
5.什麼是客戶端負載均衡
6.Spring RestTemplate中幾種常見的請求方式
7.RestTemplate的逆襲之路,從發送請求到負載均衡 markdown


負載均衡器

首先咱們來看一張上篇文章中的舊圖: 網絡

這裏寫圖片描述

這是ILoadBalancer接口的一張類關係圖,咱們就從這張圖裏看起吧。 負載均衡

AbstractLoadBalancer

AbstractLoadBalancer類的定義以下: 前後端分離

public abstract class AbstractLoadBalancer implements ILoadBalancer {

    public enum ServerGroup{
        ALL,
        STATUS_UP,
        STATUS_NOT_UP        
    }
    public Server chooseServer() {
        return chooseServer(null);
    }
    public abstract List<Server> getServerList(ServerGroup serverGroup);
    public abstract LoadBalancerStats getLoadBalancerStats();    
}

關於這個類我說如下幾點:
1. AbstractLoadBalancer實現了ILoadBalancer接口,但它是一個抽象類,它裏邊定義了一個關於服務實例的分組枚舉類,包含了三種類型的服務:ALL表示全部服務,STATUS_UP表示正常運行的服務,STATUS_NOT_UP表示下線的服務。
2. chooseServer方法毫無疑問是用來選取一個服務實例,可是要怎麼選這裏並無說,咱們之後在它的實現類裏邊尋找選取策略。
3. getServerList方法用來獲取某一個分組中全部的的服務實例。
4. getLoadBalancerStats方法用來獲取LoadBalancerStats對象,LoadBalancerStats對象中保存了每個服務的全部細節信息。 微服務

BaseLoadBalancer

BaseLoadBalancer是AbstractLoadBalancer的一個實現類,源碼比較長我就不貼出來的,咱們在這裏主要來講說BaseLoadBalancer提供了哪些功能: spa

1. 首先這個類中有兩個List集合中放的Server對象,一個List集合用來保存全部的服務實例,還有一個List集合用來保存當前有效的服務實例。
2. BaseLoadBalancer中定義了一個IPingStrategy,用來描述服務檢查策略,IPingStrategy默認實現採用了SerialPingStrategy實現,SerialPingStrategy中的pingServers方法就是遍歷全部的服務實例,一個一個發送請求,查看這些服務實例是否還有效,若是網絡環境很差的話,這種檢查策略效率會很低,若是咱們想自定義檢查策略的話,能夠重寫SerialPingStrategy的pingServers方法。
3. 在BaseLoadBalancer的chooseServer方法中(負載均衡的核心方法),咱們發現最終調用了IRule中的choose方法來找到一個具體的服務實例,IRule是一個接口,在BaseLoadBalancer它的默認實現是RoundRobinRule類,RoundRobinRule類中採用了最經常使用的線性負載均衡規則,也就是全部有效的服務端輪流調用。
4. 在BaseLoadBalancer的構造方法中會啓動一個PingTask,這個PingTask用來檢查Server是否有效,PingTask的默認執行時間間隔爲10秒。
5. markServerDown方法用來標記一個服務是否有效,標記方式爲調用Server對象的setAlive方法設置isAliveFlag屬性爲false。
6. getReachableServers方法用來獲取全部有效的服務實例列表。
7. getAllServers方法用來獲取全部服務的實例列表。
8. addServers方法表示向負載均衡器中添加一個新的服務實例列表。 code

BaseLoadBalancer的功能大概就這麼多。 視頻

DynamicServerListLoadBalancer

DynamicServerListLoadBalancer是BaseLoadBalancer的一個子類,在DynamicServerListLoadBalancer中對基礎負載均衡器的功能作了進一步的擴展,咱們來看看。

1. 首先DynamicServerListLoadBalancer類一開始就聲明瞭一個變量serverListImpl,serverListImpl變量的類型是一個ServerList<T extends Server>,這裏的泛型得是Server的子類,ServerList是一個接口,裏邊定義了兩個方法:一個getInitialListOfServers用來獲取初始化的服務實例清單;另外一個getUpdatedListOfServers用於獲取更新的服務實例清單。
2. ServerList接口有不少實現類,DynamicServerListLoadBalancer默認使用了DomainExtractingServerList類做爲ServerList的實現,可是在DomainExtractingServerList的構造方法中又傳入了DiscoveryEnabledNIWSServerList對象,查看源碼發現最終兩個清單的獲取方式是由DiscoveryEnabledNIWSServerList類來提供的。
3. DomainExtractingServerList類中的obtainServersViaDiscovery方法是用來發現服務實例並獲取的,obtainServersViaDiscovery方法的主要邏輯是這樣:首先依靠EurekaClient從服務註冊中心獲取到具體的服務實例InstanceInfo列表,而後對這個列表進行遍歷,將狀態爲UP的實例轉換成DiscoveryEnabledServer對象並放到一個集合中,最後將這個集合返回。
4. DynamicServerListLoadBalancer中還定義了一個ServerListUpdater.UpdateAction類型的服務更新器,Spring Cloud提供了兩種服務更新策略:一種是PollingServerListUpdater,表示定時更新;另外一種是EurekaNotificationServerListUpdater表示由Eureka的事件監聽來驅動服務列表的更新操做,默認的實現策略是第一種,即定時更新,定時的方式很簡單,建立Runnable,調用DynamicServerListLoadBalancer中updateAction對象的doUpdate方法,Runnable延遲啓動時間爲1秒,重複週期爲30秒。
5. 在更新服務清單的時候,調用了咱們在第一點提到的getUpdatedListOfServers方法,拿到實例清單以後,又調用了一個過濾器中的方法進行過濾。過濾器的類型有好幾種,默認是DefaultNIWSServerListFilter,這是一個繼承自ZoneAffinityServerListFilter的過濾器,具備區域感知功能。即它會對服務提供者所處的Zone和服務消費者所處的Zone進行比較,過濾掉哪些不是同一個區域的實例。

綜上,DynamicServerListLoadBalancer主要是實現了服務實例清單在運行期間的動態更新能力,同時提供了對服務實例清單的過濾功能。

ZoneAwareLoadBalancer

ZoneAwareLoadBalancer是DynamicServerListLoadBalancer的子類,ZoneAwareLoadBalancer的出現主要是爲了彌補DynamicServerListLoadBalancer的不足。因爲DynamicServerListLoadBalancer中並無重寫chooseServer方法,因此DynamicServerListLoadBalancer中負責均衡的策略依然是咱們在BaseLoadBalancer中分析出來的線性輪詢策略,這種策略不具有區域感知功能,這樣當須要跨區域調用時,可能會產生高延遲。ZoneAwareLoadBalancer重寫了setServerListForZones方法,該方法在其父類中的功能主要是根據區域Zone分組的實例列表,爲負載均衡器中的LoadBalancerStats對象建立ZoneStats並存入集合中,ZoneStats是一個用來存儲每一個Zone的狀態和統計信息。重寫以後的setServerListForZones方法主要作了兩件事:一件是調用getLoadBalancer方法來建立負載均衡器,同時建立服務選擇策略;另外一件是對Zone區域中的實例清單進行檢查,若是對應的Zone下已經沒有實例了,則將Zone區域的實例列表清空,防止節點選擇時出現異常。

OK,以上就是咱們對負載均衡器的一個簡單介紹,下一篇文章咱們將繼續介紹負載均衡策略

 

關注公衆號【江南一點雨】,專一於 Spring Boot+微服務以及先後端分離等全棧技術,按期視頻教程分享,關注後回覆 Java ,領取鬆哥爲你精心準備的 Java 乾貨!

相關文章
相關標籤/搜索