1. 程式人生 > >dubbo中registry、route、directory、cluster、loadbalance、route的關系以及一個引用操作和調用操作到底幹了啥

dubbo中registry、route、directory、cluster、loadbalance、route的關系以及一個引用操作和調用操作到底幹了啥

本質 parameter conf 自己的 序列 gis 什麽 lis 第一次

zk是比較典型場景,所以註冊中心都是以zk作為例子的

1 對於registry,提供者沒有這個,消費者才有。為什麽?
因為只有消費者才需要去註冊中心拿到provide的信息,而provider是不需要關註的,provider只需要去註冊就好。在RegistryProtocol的export方法中,可以看到在registry方法裏面直接在註冊中心寫信息就夠了。

2 RegistryDirectory是啥意思?如果有三個zk,有幾個directory?幾個registry?
一個目錄其實就是很容易想到就是一個dubbo提供者的interfacename在zk上面的/duboo+interfacename的目錄,但不僅僅是這樣,如果有多個zk,那麽有三個目錄,因為這三個目錄在不同的zk上面。

一個消費者在初始化得到引用的時候,在loadRegistries裏面,如果url裏面有多個以分號隔開的註冊中心的ip+port,那麽就得到多個註冊中心的url,那麽每個url都需要經過registryProcol處理,具體來說createProxy裏面就是要對每個註冊url進行refer操作

所以directory的構造函數裏面有兩個東西來限定唯一性:註冊中心url和provider的interfacename。對於一個消費者,假設只有一個provider的interfacename需要引用的話,在三個zk的前提下,那麽要維護三個registry,三個registry都各自有自己的directory。消費者初始化引用的時候每個directory和對應的registry都需要一個方面跟提供者一樣,去不同的zk上面的consumer寫入自己的信息,另外要分別訂閱這個interfaceface路徑下的provider、configure、route信息。第一次訂閱的時候,順便把provider的具體信息都存在directory的methodInvokerMap中,以後要調用的時候就從這裏取。

3 dubbo裏面經常說的FailoverClusterinvoer、BroadcastClusterInvoker等等這些Cluster是啥意思?

首先cluster接口只有一個方法,就是通過join得到一個invoker,不要被名字誤導了,雖然叫cluster,其實沒有保存多個invoker,並不是保存了一個集合。雖然叫join,但是其實是利用spi根據配置得到不同的cluster,可以理解成:cluster的join就是根據配置得到不同ClusterInvoker實現。當然還有一個MockClusterWrapper,所以所有的Cluster其實都被這個Wrapper都包了一層,這個是dubbo的spi註入做的,看名字就知道加這一層是為了提前攔截,方便mock測試用的。

4 Cluster和loadbalance的關系

不同的Cluster的實現裏面都有一個doInvoke方法,dubbo提供者被調用的時候都會走這個方法,因為cluster本質也是一個invoker,不同的Cluster具有不同的doInvoke實現,在遇到多個invoker調用不順利情況下 做不同處理。
而loadbalance不同,他是用來挑選優先使用哪個invoker的,一般有隨機、一致性哈希,這個也是spi來挑選的。在cluster的共同的父類實現中,也就是在doinvoke之前,都會調用一次loadbalance的select來選出優先的invoker

5 dubbo與zk的關系咋樣的,dubbo怎麽被zk通知的?

我們說過provider是不需要監聽的,消費者才要。我感覺dubbo的zklistener太繞了,dubbox稍微好點。消費者在兩個地方進行監聽:與zk連接的statechanged回調以及自己引用的interface目錄的provider、configure、route目錄發生變化的時候,也會有childchanged的回調。
statechanged回調的註冊應該比較好找,就是zkclient去連接zk的時候,建立的回調註冊。這個裏的回調處理是,一旦發現重連,那麽把已經註冊的、已經訂閱的全部劃分到failed的list裏面,zkregistry有一個心跳,定期檢查這些failed的list裏面是不是有數據,如果有那麽重新註冊、訂閱。
childchanged是在訂閱的時候註冊的,也就是doSubscribe裏面。當provider、configure、route發生變化的時候,最終調用到RegistryDirectory的notify方法,回調的傳過來的參數是當前這個目錄比如provider目錄下面的實際子節點的全部信息。以provider目錄為例子,拿到這些重要信息以後,RegistryDirectory就會根據新的provider的url-list,做一次refreshInvoker,做之前還把緩存的文件也根據這個更新的。

所以說consumer就是通過這個回調感知provider的變化的,看得出來如果zk回調出問題,dubbo就找不到提供者,並且緩存文件也壞了。並且dubbo沒有主動去輪訓檢查zk的當前信息,這塊還是比較脆弱的。
我看dubbo官網說的是,阿裏內部沒用zk,而是用自己的數據庫作為註冊中心。


6 refreshInvoker 裏面做了啥?
前面只是講到得到了一個provider的url、list,並沒有得到一個provider的實體,其實有了provider,需要使用dubboProcol的refer去真正引用一個service,與service建立長鏈接關系。底層建立transport層的通信關系,我是使用netty4看的有時間可以寫寫。
至於序列化那塊,默認用的hessian,比較繁瑣。dubbo沒有用protobuf,如果用的話,性能更好,並且代碼應該也不需要寫這麽多。所以沒有細研究了


7 消費者refer得到的到底是啥?
根據前面提到的,我們可以簡單總結下,假如有三個zk,那麽dorefer幹下面幾個事情:
創建三個registry、三個directory。
與三個registry建立長鏈接,創建consumer目錄上自己的信息,這個叫註冊。
然後訂閱provider的信息,並且把provider的url信息拿到後refreshInvoker
與這些dubbo-invoker建立連接關系


8 那麽問題來了,refer方法結果是dubbo-invoker嗎?如果是的話 就用不到cluster、loadbalance這些了。
在doRefer方法的最後,還是調用了cluster.join(directory)得到invoke返回回去。也就是最終返回了三個MockClusterWrapper,裏面是FailoverClusterInvoker(默認spi)
對於directory或者說registry做了一次cluster.join,這是因為一個directory可能相同的版本的provider都不止一個,所以不同的provider是一個cluster,這裏面存在一個選擇。

剛剛外面說了返回了三個MockClusterWrapper,但是consumer或者說我們的業務使用者來說,不應該感知這些,所以對於三個註冊中心的三個MockClusterWrapper還要做一次cluster.join:
URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
invoker = cluster.join(new StaticDirectory(u, invokers));
這次是指定用了AvailableCluster,於是又返回了一個MockClusterInvoker,裏面包裹了真正的AvailableCluster,這個AvailableCluster的doInvoke方法就是遍歷自己的invoke-list,只要可用就用這個,也就是說三個zk,只要有一個沒問題,就直接用這個zk的url代表的provider
當然這個ref還要做一次proxy動態代理才能真正返回給用戶使用


9 Route是幹啥用的,在哪裏生效的?
在執行真正的invoke時候,為了使用cluster、loadbalance,必須經過clusterinvoke,在虛基類AbstractClusterInvoker的doInvoke方法中,首先是利用directory.list針對這個invocation做一次篩選,
List<Invoker<T>> invokers = doList(invocation);可以不用考慮,就是根據調用方法拿到invokers(這裏的invokers都是通過refreshinvokers拿到的),對於StaticDirectory直接返回所有invokers。
然後會用默認的MockInvokersSelector做一次route篩選處理,通過名字知道還是為了mock調試用的。其他的route還有ConditionRouter和ScriptRouter,路由規則決定一次 dubbo 服務調用的目標服務器。dubbo官網目前是試用階段。


10 一次調用進行了兩次cluster的選擇
一次調用,首先選擇任一一個可用registry或者說directory的invoker,也就是確定用這個註冊中心。後面還要選擇到底用這個註冊中心的哪個provider,默認spi是FailoverClusterinvoer,然後走loadbalance、cluster邏輯選出真正的invoker,走dubbo調用流程

dubbo中registry、route、directory、cluster、loadbalance、route的關系以及一個引用操作和調用操作到底幹了啥