dubbo做爲阿里開發優秀的rpc服務框架,現已普遍用於各大rpc項目之間的遠程通訊,雖然阿里如今已經沒有維護dubbo的開發,可是其結構設計也是值得學習。spring
這部分只是簡單介紹dubbo的結構圖解,可能會有些複雜,但確實是dubbo設計的精髓所在。服務器
提供方和消費方都是經過註冊中心來交互,提供方依賴註冊中心來暴露需提供的接口,服務方經過註冊中心來調用接口。提供方和註冊方與註冊中心之間是無狀態聯繫的,也就是說它倆不論說掛掉了不會影響另外一方的使用。這也是大部分生產/消費框架設計最科學的地方,雙方進行無狀態交互,互不干涉互不影響,軟件設計的觀察者模式也與此相似。網絡
基於dubbo.jar內的META-INF/spring.handlers配置,Spring在遇到dubbo名稱空間時,會回調DubboNamespaceHandler。全部dubbo的標籤,都統一用DubboBeanDefinitionParser進行解析,基於一對一屬性映射,將XML標籤解析爲Bean對象。在ServiceConfig.export()或ReferenceConfig.get()初始化時,將Bean對象轉換URL格式,全部Bean屬性轉成URL的參數。而後將URL傳給Protocol擴展點,基於擴展點的Adaptive機制,根據URL的協議頭,進行不一樣協議的服務暴露或引用。負載均衡
(1) 只暴露服務端口:框架
在沒有註冊中心,直接暴露提供者的狀況下,即:異步
<dubbo:service regisrty="N/A" /> or <dubbo:registry address="N/A" />socket
ServiceConfig解析出的URL的格式爲:基於擴展點的Adaptive機制,經過URL的"dubbo://"協議頭識別,直接調用DubboProtocol的export()方法,打開服務端口。ide
dubbo://service-host/com.foo.FooService?version=1.0.0工具
(2) 向註冊中心暴露服務:學習
在有註冊中心,須要註冊提供者地址的狀況下,即:
<dubbo:registry address="zookeeper://10.20.153.10:2181" />
ServiceConfig解析出的URL的格式爲:
registry://registry-host/com.alibaba.dubbo.registry.RegistryService?export=URL.encode("dubbo://service-host/com.foo.FooService?version=1.0.0")
基於擴展點的Adaptive機制,經過URL的"registry://"協議頭識別,就會調用RegistryProtocol的export()方法,將export參數中的提供者URL,先註冊到註冊中心,再從新傳給Protocol擴展點進行暴露:基於擴展點的Adaptive機制,經過提供者URL的"dubbo://"協議頭識別,就會調用DubboProtocol的export()方法,打開服務端口。
dubbo://service-host/com.foo.FooService?version=1.0.0
(1) 直連引用服務:
在沒有註冊中心,直連提供者的狀況下,即:
<dubbo:reference url="dubbo://service-host/com.foo.FooService?version=1.0.0" />
ReferenceConfig解析出的URL的格式爲:基於擴展點的Adaptive機制,經過URL的"dubbo://"協議頭識別,直接調用DubboProtocol的refer()方法,返回提供者引用。
dubbo://service-host/com.foo.FooService?version=1.0.0
(2) 從註冊中心發現引用服務:
在有註冊中心,經過註冊中心發現提供者地址的狀況下,即:
<dubbo:registry address="zookeeper://10.20.153.10:2181" />
ReferenceConfig解析出的URL的格式爲:
registry://registry-host/com.alibaba.dubbo.registry.RegistryService?refer=URL.encode("consumer://consumer-host/com.foo.FooService?version=1.0.0")
基於擴展點的Adaptive機制,經過URL的"registry://"協議頭識別,就會調用RegistryProtocol的refer()方法,基於refer參數中的條件,查詢提供者URL,如:基於擴展點的Adaptive機制,經過提供者URL的"dubbo://"協議頭識別,就會調用DubboProtocol的refer()方法,獲得提供者引用。
dubbo://service-host/com.foo.FooService?version=1.0.0
而後RegistryProtocol將多個提供者引用,經過Cluster擴展點,假裝成單個提供者引用返回。
能夠看到ServiceConfig類拿到對外提供服務的實際類ref,而後經過代理工廠類ProxyFactory類的getInvoker方法使用ref生成一個抽象代理對象AbstractProxyInvoker實例,到這一步就完成具體服務到Invoker的轉化。接下來就是Invoker轉換到Exporter的過程。
能夠看到引用配置對象ReferenceConfig的init方法調用Protocol的refer方法生成Invoker實例(如上圖中的紅色部分),這是服務消費的關鍵。接下來把Invoker轉換爲客戶端須要的接口。
能夠看到引用配置對象ReferenceConfig的init方法調用Protocol的refer方法生成Invoker實例(如上圖中的紅色部分),這是服務消費的關鍵。接下來把Invoker轉換爲客戶端須要的接口。
Dubbo協議的Invoker轉爲Exporter發生在DubboProtocol類的export方法,它主要是打開socket偵聽服務,並接收客戶端發來的各類請求,通信細節由Dubbo本身實現。
RMI協議的Invoker轉爲Exporter發生在RmiProtocol類的export方法,
它經過Spring或Dubbo或JDK來實現RMI服務,通信細節這一塊由JDK底層來實現,這就省了很多工做量。
關於dubbo的設計還有筆者還有不少須要學習的地方,想學習更過的dubbo技術能夠去參考dubbo的官方API http://dubbo.io/.