dubbo之export淺析

設計

整體設計圖(引用自官網(wǎng))

以ServiceConfig類為起點,主要過程為執(zhí)行invoker和Exporter兩個操作,這樣看起來就清晰了。下面是整個export的時序圖,從中可以看出ServiceConfig動作為createInvoker()和export(),Protocol執(zhí)行了init()和exported()。

時序圖(引用自官網(wǎng))

注冊中心暴露服務

ServiceConfig 解析出的 URL 的格式為: registry://registry-host/com.alibaba.dubbo.registry.RegistryService?export=URL.encode("dubbo://service-host/com.foo.FooService?version=1.0.0")

基于擴展點自適應機制,通過 URL 的 registry:// 協(xié)議頭識別,就會調(diào)用 RegistryProtocolexport() 方法,將 export 參數(shù)中的提供者 URL,先注冊到注冊中心。

再重新傳給 Protocol 擴展點進行暴露: dubbo://service-host/com.foo.FooService?version=1.0.0,然后基于擴展點自適應機制,通過提供者 URL 的 dubbo:// 協(xié)議頭識別,就會調(diào)用 DubboProtocolexport() 方法,打開服務端口。

暴露服務主過程

首先 ServiceConfig 類拿到對外提供服務的實際類 ref(如:HelloWorldImpl),然后通過 ProxyFactory 類的 getInvoker 方法使用 ref 生成一個 AbstractProxyInvoker 實例,到這一步就完成具體服務到 Invoker 的轉(zhuǎn)化。接下來就是 Invoker 轉(zhuǎn)換到 Exporter 的過程。

Dubbo 處理服務暴露的關(guān)鍵就在 Invoker 轉(zhuǎn)換到 Exporter 的過程,上圖中的紅色部分。 Dubbo 和 RMI 這兩種典型協(xié)議的實現(xiàn)如下:

  • Dubbo 的實現(xiàn)
    Dubbo 協(xié)議的 Invoker 轉(zhuǎn)為 Exporter 發(fā)生在 DubboProtocol 類的 export 方法,它主要是打開 socket 偵聽服務,并接收客戶端發(fā)來的各種請求,通訊細節(jié)由 Dubbo 自己實現(xiàn)。

  • RMI 的實現(xiàn)
    RMI 協(xié)議的 Invoker 轉(zhuǎn)為 Exporter 發(fā)生在 RmiProtocol類的 export 方法,它通過 Spring 或 Dubbo 或 JDK 來實現(xiàn) RMI 服務,通訊細節(jié)這一塊由 JDK 底層來實現(xiàn),這就省了不少工作量。

暴露過程

初始化的時候掃描配置文件,調(diào)用父類的方法registerBeanDefinitionParser(),存入一個名為parsers的hashMap中。

image.png

然后ServiceConfig類中的export方法不知道怎么的就執(zhí)行了到這了,可以看到方法里可以立即加載和延時加載。

image.png

在調(diào)用當前類的doExport方法。方法中檢查了加載的參數(shù)完不完整,正不正確。

img

接下來進入doExportUrls();方法,可以看到這里有個for循環(huán),可以接受多個注冊地址。

image.png

然后進入doExportUrlsFor1Protocol()方法,這個方法比較長,前半段負責檢查拼裝參數(shù),還有一些邏輯,我覺得最重要的是下面箭頭所指的兩行代碼,第一個是通過代理工廠生成代理方法,第二個是暴露服務。

image.png

第二個會進入ProtocolFilterWrapper的export方法,調(diào)用buildInvokerChain鏈

image.png

會默認進入DubboProtocol里,在這里的調(diào)用openServer()

image.png

仔細看看openServer()都干了啥,openServer調(diào)用createServer(url),createServer(url)中最重要的bind方法。

image.png

一步一步走下去,看到是調(diào)用了Transporters的bind方法。

image.png

點進去bind方法,可以看到getTransporter()這個方法返回了一個Transporter對象,看一下Transporter的接口,bind方法上有@Adaptive注解,在 Dubbo 的 ExtensionLoader 的擴展點類對應的 Adaptive 實現(xiàn)是在加載擴展點里動態(tài)生成。指定提取的 URL 的 Key 通過 @Adaptive 注解在接口方法上提供。對于 bind() 方法,Adaptive 實現(xiàn)先查找 server key,如果該 Key 沒有值則找 transport key 值,來決定代理到哪個實際擴展點。默認使用SPI中設定的值,所以是netty。

image.png

transporter

Adaptive

在NettyServer繼承了AbstractServer并且實現(xiàn)了Server接口,可以看到NettyServer在構(gòu)造方法中實現(xiàn)了父類的構(gòu)造方法,調(diào)用了doOpen,也可以看到打出start bind export的日志。

image.png

image.png

image.png

然后進入到RegistryProtocol的export方法,在這里注冊服務到zookeeper


image.png

調(diào)用下面方法,設置協(xié)議等

image.png

執(zhí)行這句 final Registry registry = getRegistry(originInvoker);


image.png

調(diào)用AbstractRegistryFactory的getRegistry

image.png

ZookeeperRegistryFactory的createRegistry的方法,因為ZookeeperRegistryFactory繼承了AbstractRegistryFactory,AbstractRegistryFactory實現(xiàn)了RegistryFactory接口,而這個接口的getRegistry方法注解為@Adaptive({"protocol"}),之前有設置協(xié)議為zookeeper,所以根據(jù)名稱選擇了ZookeeperRegistryFactory的實現(xiàn)。

image.png

這里調(diào)用zookeeperTransporter的connect,就跟調(diào)用netty一樣的


image.png

默認Zkclient的實現(xiàn)


image.png

在這里創(chuàng)建連接
image.png

創(chuàng)建成功之后,dubbo自己存一份


image.png

然后返回RegistryProtocol的export方法,添加一些訂閱監(jiān)聽
最后回到ServiceConfig的export方法,整個服務暴露完成。


參考:http://dubbo.io/books/dubbo-dev-book/design.html
各位大神多多指導

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容