前言

本來是想把整個dubbo源碼解析一次性弄完,再做成一個系列來發布的,但是正巧最近有位好朋友要去杭州面試,就和我交流了一下。本著對dubbo源碼略有心得的心態,在交流過程中也發表了個人的一些粗劣的拙見。但是非常不幸的是,交流過程中我這位朋友問到了幾個問題,我卻沒能回答得上,讓我感到十分慚愧。故而將原計劃提前,並且定期整理,做到定期更新一篇dubbo源碼解析,好讓自己的知識盲點儘早暴露出來。本篇講的就是dubbo的一個重要概念,集群容錯。既然你已經在看源碼解析了,那麼我就假設你對dubbo的使用上有一定的經驗,對集群容錯的簡單介紹。

前期鋪墊

官網介紹圖

這張是官網的對於集群容錯的架構設計圖,即使你有一定的使用經驗,第一眼看到這個圖可能還是有些懵逼。因為這個圖是從設計的角度畫出來的,而不是使用的角度。但是即使這個圖你看不懂也不影響你對本文的閱讀,但是你必須要記住三個關鍵詞,因為這三個關鍵詞接下來會貫穿全文,他們就是DirectoryRouterLoadBalance

再接下來給大家一張"地圖","地圖"上我已經標記了序號,再下面的源碼分析中,我也會實時提醒我們所在的位置,以至於不會迷失方向。

執行時序圖

環境準備

既然是集群,那麼首先要啟動兩個Provider,我這裡是一個虛擬機,一個本地的方式,因為環境準備不是本文重點,因此略過。本文所用到的源碼是2.5.4版本,可以在guihub上找到。

正式發車

這次示例選用的源碼用dubbo-demo的dubbo-demo-consumer,如果對dubbo原理有些簡單的了解就知道,他給介面注入的不是介面的實現類,而是一個代理類,如下圖:

接著自然是到了代理類的invoke方法里,從圖中我們也可以看出,他用的是jdk的動態代理。

下面要開始緊盯著地圖了,他現在就要開始執行地圖中的序號1,此時我們抵達MockClusterInvoker這個類。

執行invoke就要開始進入到集群,也就是Cluster,現在第一個關鍵詞Directory已經浮出水面了。

現在到了AbstractDirectory,也就是序號3。

這個methodInvokerMap也比較重要,後面的文章會講一下這個,但是我們這部分代碼就可以從出,他是要從methodInvokerMap中取出invokers如圖所示:

將invokers返回後(序號5),下面來到了第二個關鍵詞,Router,開始進入路由,現在我們到了序號6,此時到了MockInvokersSelector類,不要看類名和Router沒有關係,其實他是Router介面的實現類,從官網的介紹圖中我們也可以看到Router分為Script和Condition兩種,翻譯過來也就是腳本路由和條件路由這個後面再詳細介紹,本篇主要介紹整體架構。

源碼的命名是很規範的,從getNormalInvokers就可以得知,他是要拿到能正常執行的invokers,並將其返回,也就是序號7。

這個時候我們再次回到了AbstractClusterInvoker這個類,我們先不急著往下走,先適時做個總結。因為三個關鍵詞,現在都已經出現了兩個,那這個時候要回憶一下上面這些步驟,做一個總結。上面出現的這兩個關鍵詞,其實無非就是做兩件事:

  • 在Directory中找出本次集群中的全部invokers
  • 在Router中,將上一步的全部invokers挑選出能正常執行的invokers

對應到"地圖",也就是序號5和序號7。(再次提醒,一定要緊跟地圖的序號,不然很容易迷失方向)。

從上面步驟我們也知道,已經挑選出能正常執行的invokers了,但是假如2個做集群,但是這兩個都是正常的,我到底要執行哪一個呢?帶著這個問題,我們繼續往下看。

根據官網的描述:

在集群調用失敗時,Dubbo 提供了多種容錯方案,預設為 failover 重試。

所以這個時候是到了FailoverClusterInvoker類,但是如果你配置的是Failover Cluster(快速失敗),Failsafe Cluster(失敗安全),Failback Cluster(失敗自動恢復),Forking Cluster(並行調用多個伺服器,只要一個成功即返回),Broadcast Cluster(廣播調用所有提供者,逐個調用,任意一台報錯則報錯)他也會到達相應的類。

下面就要開始第三個關鍵詞浮出水面,也就是LoadBalance(負載均衡),此時的位置是序號11,仔細留心源碼的注釋,其實這裡可以出一個面試題,比如:

dubbo的負載均衡策略是怎麼樣的?

為什麼這可以作為一道面試題,因為他可以區分三個層次的人。

  • 如果是沒有使用過,或者一直停留在使用層次的人,肯定不會留級到這個負載均衡策略;
  • 根據官網介紹在集群負載均衡時,Dubbo 提供了多種均衡策略,預設為 random 隨機調用。如果能回答出,預設為隨機調用的,說明還是有一定的使用經驗,留意到官網的介紹;
  • 如果能回答出,預設為隨機調用,但是如果集群的數量為2,那麼將退化成輪詢。如果能回答到這個,那這個人就是有一定追求,不僅留心文檔介紹,而且是看過源碼,注意細節的人(比如本文作者肥朝 ^_^ )。

根據前面我們知道,現在已經有兩個備選的invokers,但是究竟哪一個能執行,這個需要LoadBalance來決定。這裡涉及到了一定的演算法,後面我也會有一篇文章加以介紹。劇透一下,這個在2.5.4的版本中,這個演算法還是存在一些小的bug,此時我們的位置是序號13。

到達終點站,我們回憶總結一下,文初提到的三個關鍵詞,在這個集群容錯的整體架構過程中,dubbo究竟做了什麼?其實也就是三件事:

  • 在Directory中找出本次集群中的全部invokers
  • 在Router中,將上一步的全部invokers挑選出能正常執行的invokers
  • 在LoadBalance中,將上一步的能正常的執行invokers中,根據配置的負載均衡策略,挑選出需要執行的invoker

推薦閱讀:

相关文章