Dubbo集群容錯與負載均衡策略

  • 2019 年 12 月 20 日
  • 筆記

一、 Dubbo集群容錯策略概述

當我們進行系統設計時候,不僅要考慮正常邏輯下程式碼該如何走,還要考慮異常情況下程式碼邏輯應該怎麼走。當服務消費方調用服務提供方的服務出現錯誤時候,Dubbo 提供了多種容錯方案,預設模式為 failover,也就是失敗重試。

下面看下 Dubbo 提供的集群容錯模式:

  • Failover Cluster:失敗重試

當服務消費方調用服務提供者失敗後自動切換到其他服務提供者伺服器進行重試。這通常用於讀操作或者具有冪等的寫操作,需要注意的是重試會帶來更長延遲。可通過 retries="2" 來設置重試次數(不含第一次)。

介面級別配置重試次數方法可以使用<dubbo:reference retries="2" />,如上配置當服務消費方調用服務失敗後,會再重試兩次,也就是說最多會做三次調用,這裡的配置對該介面的所有方法生效。

當然你也可以針對某個方法配置重試次數如下:

<dubbo:reference>     <dubbo:method name="sayHello" retries="2" />  </dubbo:reference>
  • Failfast Cluster:快速失敗

當服務消費方調用服務提供者失敗後,立即報錯,也就是只調用一次。通常這種模式用於非冪等性的寫操作。

  • Failsafe Cluster:安全失敗

當服務消費者調用服務出現異常時,直接忽略異常。這種模式通常用於寫入審計日誌等操作。

  • Failback Cluster:失敗自動恢復

當服務消費端調用服務出現異常後,在後台記錄失敗的請求,並按照一定的策略後期再進行重試。這種模式通常用於消息通知操作。

  • Forking Cluster:並行調用

當消費方調用一個介面方法後,Dubbo Client 會並行調用多個服務提供者的服務,只要一個成功即返回。這種模式通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。如下程式碼可通過 forks="4" 來設置最大並行數:

    <dubbo:reference id="userService"          interface="com.test.UserServiceBo" group="dubbo" version="1.0.0" cluster="forking">          <dubbo:parameter key="forks" value="4" />      </dubbo:reference>
  • Broadcast Cluster:廣播調用

當消費者調用一個介面方法後,Dubbo Client 會逐個調用所有服務提供者,任意一台調用異常則這次調用就標誌失敗。這種模式通常用於通知所有提供者更新快取或日誌等本地資源資訊。

如上,Dubbo 本身提供了豐富的集群容錯模式,但是如果您有訂製化需求,可以根據 Dubbo 提供的擴展介面 Cluster 進行訂製。

在《Dubbo服務消費流程剖析》一節中我們知道服務消費端具體是調用了集群容錯策略的doInvoke方法,所以下面我們主要剖析幾種比較常見的集群容錯的doInvoke方法,以及如何自定義集群容錯策略,另外所有集群容錯策略都是繼承自抽象類AbstractClusterInvoker。

首先我們來看下服務消費端發起遠程調用的一個簡化時序圖,如下圖6.1.1:

image.png

圖6.1.1

如上時序圖圖6.1.1採用默認的FailOver集群容錯方法時候調用時序圖,可知調用集群容錯是在服務降級策略後面進行的,集群容錯FailoverClusterInvoker內部首先會調用父類AbstractClusterInvoker的list方法來獲取invoker列表,可知是從RegistryDirectory管理的RouterChain的route方法獲取保存的invoker列表(可以翻看《Directory目錄與Router路由服務》一節進行回顧)

下面幾章我們對各種集群容錯策略源碼進行分析。

二、 Dubbo負載均衡策略概述

當服務提供方是集群的時候,為了避免大量請求一直落到一個或者幾個服務提供方機器上,從而使這些機器負載很高,甚至打死,需要做一定的負載均衡策略。Dubbo 提供了多種均衡策略,預設為 random ,也就是每次隨機調用一台服務提供者的服務。

Dubbo 提供的負載均衡策略有如下幾種:

  • Random LoadBalance:隨機策略。按照概率設置權重,比較均勻,並且可以動態調節提供者的權重。
  • RoundRobin LoadBalance:輪循策略。輪循,按公約後的權重設置輪循比率。會存在執行比較慢的服務提供者堆積請求的情況,比如一個機器執行的非常慢,但是機器沒有掛(如果掛了,那麼當前機器會從 ZooKeeper 的服務列表刪除),當很多新的請求到達該機器後,由於之前的請求還沒處理完畢,會導致新的請求被堆積,久而久之,所有消費者調用這台機器上的請求都被阻塞。
  • LeastActive LoadBalance:最少活躍調用數。如果每個提供者的活躍數相同,則隨機選擇一個。在每個服務提供者裡面維護著一個活躍數計數器,用來記錄當前同時處理請求的個數,也就是並發處理任務的個數。所以如果這個值越小說明當前服務提供者處理的速度很快或者當前機器的負載比較低,所以路由選擇時候就選擇該活躍度最小的機器。如果一個服務提供者處理速度很慢,由於堆積,那麼同時處理的請求就比較多,也就是活躍調用數目越大,這使得慢的提供者收到更少請求,因為越慢的提供者的活躍度越來越大。
  • ConsistentHash LoadBalance 一致性 Hash 策略。一致性 Hash,可以保證相同參數的請求總是發到同一提供者,當某一台提供者掛了時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動。

如上所述Dubbo提供了豐富的負載均衡策略,但是如果您有訂製化需求,可以基於 Dubbo 提供的擴展介面 LoadBalance 進行訂製。

AbstractLoadBalance實現了LoadBalance介面,上面的各種負載均衡策略是繼承了AbstractLoadBalance方法,但是重寫了其doSelect方法,所以下面我們重點看每種負載均衡策略的doSelect方法。

這裡我們先看下從消費端發起請求到處理負載均衡的時序圖,如下圖6.9.1:

image.png

圖6.9.1

如上時序圖6.9.1,消費端發起遠程調用後會先經過步驟4進行服務降級檢查,發現沒有設置降級策略會執行步驟5進入集群容錯invoker,其內部會先執行步驟6從RegistryDirectory裡面獲取經過服務路由規則過濾後的服務提供者的invokers列表,然後執行程式碼8到11根據具體負載均衡策略從invoker列表選擇一個invoker,最後使用選擇的invoke執行步驟12發起遠程調用。

下面幾章我們對各種負載均衡策略源碼進行分析。

三、總結

Dubbo框架提供了幾種常見的Dubbo集群容錯與負載均衡策略,當業務需要訂製時,可以基於SPI介面進行訂製。本章摘錄自《深度剖析Apache Dubbo核心技術內幕》