為了避免單點故障,現在的應用通常至少會部署在兩台服務器上。對於一些負載比較高的服務,會部署更多的服務器。這樣,在同一環境下的服務提供者數量會大於1。對於服務消費者來說,同一環境下出現了多個服務提供者。這時會出現一個問題,服務消費者需要決定選擇哪個服務提供者進行調用。另外服務調用失敗時的處理措施也是需要考慮的,是重試呢,還是拋出異常,亦或是只打印異常等。為了處理這些問題,Dubbo 定義了集群接口 Cluster 以及 Cluster Invoker。集群 Cluster 用途是將多個服務提供者合並為一個 Cluster Invoker,並將這個 Invoker 暴露給服務消費者。這樣一來,服務消費者只需通過這個 Invoker 進行遠程調用即可,至於具體調用哪個服務提供者,以及調用失敗后如何處理等問題,現在都交給集群模塊去處理。集群模塊是服務提供者和服務消費者的中間層,為服務消費者屏蔽了服務提供者的情況,這樣服務消費者就可以專心處理遠程調用相關事宜。比如發請求,接受服務提供者返回的數據等。這就是集群的作用。
一 選擇集群容錯方式
集群容錯機制是交由 org.apache.dubbo.rpc.cluster.Cluster 接口的子類處理,為了清楚該接口有哪些擴展類,不妨打開該類的 Dubbo SPI 配置文件(擴展點的全限定名)一觀:
mock=org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterWrapper
failover=org.apache.dubbo.rpc.cluster.support.FailoverCluster
failfast=org.apache.dubbo.rpc.cluster.support.FailfastCluster
failsafe=org.apache.dubbo.rpc.cluster.support.FailsafeCluster
failback=org.apache.dubbo.rpc.cluster.support.FailbackCluster
forking=org.apache.dubbo.rpc.cluster.support.ForkingCluster
available=org.apache.dubbo.rpc.cluster.support.AvailableCluster
mergeable=org.apache.dubbo.rpc.cluster.support.MergeableCluster
broadcast=org.apache.dubbo.rpc.cluster.support.BroadcastCluster
registryaware=org.apache.dubbo.rpc.cluster.support.RegistryAwareCluster
1
2
3
4
5
6
7
8
9
10
理論上來說,Dubbo 的集群容錯機制就有以上 10 種,且還可從 Cluster 接口上的 @SPI 可知,其默認的擴展類為 FailoverCluster。
@SPI(FailoverCluster.NAME)
public interface Cluster {
@Adaptive
<T> Invoker<T> join(Directory<T> directory) throws RpcException;
}
1
2
3
4
5
6
那么在真正調用時,可通過設置 <dubbo:service> 標簽中 cluster 屬性,其值分別對應Cluster 擴展點配置文件中的 key,以匹配對應的容錯機制。
二 前置動作
集群容錯真正發生在消費端。當消費端發起調用時,會先從服務目錄查詢滿足需求的服務提供者信息,在此基礎上進行路由,路由后的結果才會真正進行容錯處理。所以,就會有如下的活動圖:
三 容錯機制原理
3.1 Failover Cluster
失敗自動切換機制是由 FailoverClusterInvoker 類控制。在調用失敗時,會自動切換服務提供者信息進行重試。通常用於讀操作,但重試會帶來更長延遲。默認配置下,Dubbo 會使用這種機制作為缺省集群容錯機制。下圖展示了 Failover Cluster 機制的工作原理。
如上,首先是獲取重試次數,然后根據重試次數進行循環調用,失敗后進行重試。在循環內,首先是通過負載均衡組件選擇一個 Invoker,然后再通過這個 Invoker 的 invoke 方法進行遠程調用。如果失敗了,記錄下異常,並進行重試。
在源碼中是通過如下代碼獲取重試次數:
int len=getUrl().getMethodParameter(methodName, Constants.RETRIES_KEY,Constants.DEFAULT_RETRIES)+1;
1
其中,常量 Constants.RETRIES_KEY 的值為 “retries”,Constants.DEFAULT_RETRIES 的值為 2。表示:從 url 中獲取該方法中 retries 屬性的值,值為空時取默認值 2。但是在最后還有一個 +1 的動作,表示獲取的最終值為 重試次數 + 1,即執行遠程調用的最大次數為重試次數 + 1次。
3.2 Failback Cluster
失敗自動恢復會在調用失敗后,返回一個空結果給服務消費者。並通過定時任務對失敗的調用進行重試,適合執行消息通知等操作。下面來看一下它的實現邏輯。
3.3 Failfast Cluster
快速失敗只會進行一次調用,失敗后立即拋出異常。適用於冪等操作,比如新增記錄。實現邏輯如下:
3.4 Failsafe Cluster
失敗安全是指,當調用過程中出現異常時,僅會打印異常,而不會拋出異常。適用於寫入審計日志等操作。
3.5 Forking Cluster
並行調用多個服務提供者會在運行時通過線程池創建多個線程,並發調用多個服務提供者。只要有一個服務提供者成功返回了結果,doInvoke 方法就會立即結束運行。ForkingClusterInvoker 的應用場景是在一些對實時性要求比較高讀操作(注意是讀操作,並行寫操作可能不安全)下使用,但這將會耗費更多的資源。下面來看該類的實現原理。
3.6 Broadcast Cluster
BroadcastClusterInvoker 會逐個調用每個服務提供者,如果其中一台報錯,再循環調用結束后,BroadcastClusterInvoker 會拋出異常。該類通常用於通知所有提供者更新緩存或日志等本地資源信息。
TODO
其他的容錯機制原理待補充。
————————————————
版權聲明:本文為CSDN博主「Ernest.Wu」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_29116427/article/details/89812535