dubbo源碼分析13 之 集羣容錯 Invoke

在集中式環境中服務的機器臺只有一臺,這樣對於服務不僅存在服務單點故障問題而且還存在流量問題。爲了解決這個問題,就引入的分佈式與集羣概念。

分佈式:一個業務分拆多個子業務,部署在不同的服務器上
集羣:同一個業務,部署在多個服務器上

1、 dubbo 服務治理

當請求來臨時,如何從多個服務器中,選擇一個有效、合適的服務器,這個集羣所需要面對一問題。所以在集羣裏面就引申出負載均衡(LoadBalance),高可用(HA),路由(Route)等概念。我們來看一下 dubbo 在進行服務調用的時候是如何處理的。

在這裏插入圖片描述

這張集羣容錯包含以下幾個角色:

  • Invoker:對 Provider (服務提供者) 的一個可調用 Service 接口的抽象,Invoker 封裝了 Provider 地址及 Service 接口信息。
  • ClusterDirectory 中的多個 Invoker 僞裝成一個 Invoker,對上層透明,僞裝過程包含了容錯邏輯,調用失敗後,重試另一個
  • Directory:代表多個 Invoker,可以把它看成 List<Invoker> ,但與 List 不同的是,它的值可能是動態變化的,比如註冊中心推送變更
  • Router : 負責從多個Invoker 中按路由規則選出子集,比如讀寫分離,應用隔離等
  • LoadBalanceLoadBalance 負責從多個 Invoker 中選出具體的一個用於本次調用,選的過程包含了負載均衡算法,調用失敗後,需要重選.

2、集羣容錯

下面我們來分析一下 Cluster, 也就是集羣。集羣裏面包含:集羣與容錯兩個概念。下面我們來看一下維基百科對於集羣與容錯的描述。

2.1 集羣

計算機集羣是一組鬆散或緊密連接的計算機,它們協同工作,因此在許多方面,它們可以被看作是一個單一的系統。與網格計算機不同,計算機集羣使每個節點集執行相同的任務,由軟件控制和調度。

集羣的組件通常通過快速的本地區域網絡連接到一起,每個節點(計算機用作服務器)運行自己的操作系統實例。在大多數情況下,所有的節點都使用相同的硬件1更好的源和相同的操作系統,儘管在某些設置中(例如使用開放源碼集羣應用程序資源(OSCAR)),不同的操作系統可以在每個計算機或不同的硬件上使用。

2.2 容錯

容錯是一種屬性,它使系統能夠在出現故障(或內部一個或多個故障)的情況下繼續正常運行。如果它的運行質量下降,那麼下降與失敗的嚴重程度成正比,與一個天真的設計系統相比,即使是很小的故障也會導致完全崩潰。

在高可用性或生命關鍵系統中,容錯是特別需要的。當系統的某些部分被分解時,維護功能的能力被稱爲優雅的降級

3、Cluster & Invoker

下面我們來看一下 Cluster & Invoker 的接口定義

Cluster

@SPI(FailoverCluster.NAME)
public interface Cluster {

    /**
     * Merge the directory invokers to a virtual invoker.
     *
     * @param <T>
     * @param directory
     * @return cluster invoker
     * @throws RpcException
     */
    @Adaptive
    <T> Invoker<T> join(Directory<T> directory) throws RpcException;

}

Cluster 只定義了一個方法 join ,它的作用是將目錄下面的 invoker 列表合併到虛擬調用程序中。其實就是把 Provider 端暴露的調用合併到一個集羣當中。外部調用的時候不管這個服務到底有幾個提供者,Cluster 將 Directory 中的多個 Invoker 僞裝成一個 Invoker,對上層透明,僞裝過程包含了容錯邏輯,調用失敗後,重試另一個。

Invoker

public interface Invoker<T> extends Node {

    /**
     * get service interface.
     *
     * @return service interface.
     */
    Class<T> getInterface();

    /**
     * invoke.
     *
     * @param invocation
     * @return result
     * @throws RpcException
     */
    Result invoke(Invocation invocation) throws RpcException;

}

Invoker 是 Dubbo 領域模型中非常重要的一個概念,很多設計思路都是向它靠攏。這就使得 Invoker 滲透在整個實現代碼裏。 下面我們用一個官方的圖來說明最重要的兩種 Invoker:服務提供 Invoker 和服務消費 Invoker:

在這裏插入圖片描述

爲了更好的解釋上面這張圖,我們結合服務消費和提供者的代碼示例來進行說明:

服務消費者代碼:

public class DemoClientAction {

    private DemoService demoService;

    public void setDemoService(DemoService demoService) {
        this.demoService = demoService;
    }

    public void start() {
        String hello = demoService.sayHello("world" + i);
    }
}

上面代碼中的 DemoService 就是上圖中服務消費端的 proxy,用戶代碼通過這個 proxy 調用其對應的 Invoker 5,而該 Invoker 實現了真正的遠程服務調用。

服務提供者代碼:

public class DemoServiceImpl implements DemoService {

    public String sayHello(String name) throws RemoteException {
        return "Hello " + name;
    }
}

上面這個類會被封裝成爲一個 AbstractProxyInvoker 實例,並新生成一個 Exporter 實例。這樣當網絡通訊層收到一個請求後,會找到對應的 Exporter 實例,並調用它所對應的 AbstractProxyInvoker 實例,從而真正調用了服務提供者的代碼。Dubbo 裏還有一些其他的 Invoker 類,但上面兩種是最重要的。

4、集羣容錯

在 dubbo 源碼中, 在包 com.alibaba.dubbo.rpc.cluster.support 中,我們可以看到 Cluster 和 Invoker 是成對出現的。

在這裏插入圖片描述

下面我們通過類圖來看一下它們之間的關係:

在這裏插入圖片描述

每一個 Cluster 其實都是創建一個 Cluster 調用的實例,Cluster 把集羣調用功能委託給 AbstractClusterInvoker (抽象集羣調用)。其實最終返回給 Consumer 的 Invoker 實例是 MockClusterInvoker 對象。這個對象持有一個 RegistryDirectory 實例(服務自動發現與註冊)與一個 FailoverClusterInvoker 實例(失敗轉移,當出現失敗,重試其它服務器,通常用於讀操作,但重試會帶來更長延遲。)

在這裏插入圖片描述

集羣容錯主要包括以下幾種模式:

  • Failover Cluster:失敗自動切換,當出現失敗,重試其它服務器 。通常用於讀操作,但重試會帶來更長延遲。可通過 retries="2" 來設置重試次數(不含第一次)。
  • Failfast Cluster:快速失敗,只發起一次調用,失敗立即報錯。通常用於非冪等性的寫操作,比如新增記錄。
  • Failsafe Cluster:失敗安全,出現異常時,直接忽略。通常用於寫入審計日誌等操作。
  • Failback Cluster:失敗自動恢復,後臺記錄失敗請求,定時重發。通常用於消息通知操作。
  • Forking Cluster:並行調用多個服務器,只要一個成功即返回。通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。可通過 forks=“2” 來設置最大並行數。
  • Broadcast Cluster:廣播調用所有提供者,逐個調用,任意一臺報錯則報錯 2。通常用於通知所有提供者更新緩存或日誌等本地資源信息。

參考地址:
1、http://en.wikipedia.org/wiki/Computer_cluster
2、http://en.wikipedia.org/wiki/Fault-tolerant_system
3、http://dubbo.apache.org/books/dubbo-user-book/demos/fault-tolerent-strategy.html
4、http://dubbo.apache.org/books/dubbo-dev-book/implementation.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章