dubbo結構及通訊簡介

1、導論

dubbo做爲阿里開發優秀的rpc服務框架,現已普遍用於各大rpc項目之間的遠程通訊,雖然阿里如今已經沒有維護dubbo的開發,可是其結構設計也是值得學習。spring

2、結構簡介

這部分只是簡單介紹dubbo的結構圖解,可能會有些複雜,但確實是dubbo設計的精髓所在。服務器

一、各層介紹

  1. config,配置層,對外配置接口,以ServiceConfig, ReferenceConfig爲中心,能夠直接new配置類,也能夠經過spring解析配置生成配置類,dubbo的相關配置都是該對象在維護。
  2. proxy,服務代理層,服務接口透明代理,生成服務的客戶端Stub和服務器端Skeleton,以ServiceProxy爲中心,擴展接口爲ProxyFactory。
  3. registry,註冊中心層,封裝服務地址的註冊與發現,以服務URL爲中心,擴展接口爲RegistryFactory, Registry, RegistryService。
  4. cluster,路由層,封裝多個提供者的路由及負載均衡,並橋接註冊中心,以Invoker爲中心,擴展接口爲Cluster, Directory, Router, LoadBalance。
  5. monitor,監控層,RPC調用次數和調用時間監控,以Statistics爲中心,擴展接口爲MonitorFactory, Monitor, MonitorService。
  6. protocol,遠程調用層,封將RPC調用,以Invocation, Result爲中心,擴展接口爲Protocol, Invoker, Exporter。
  7. exchange,信息交換層,封裝請求響應模式,同步轉異步,以Request, Response爲中心,擴展接口爲Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer。
  8. transport,網絡傳輸層,抽象mina和netty爲統一接口,以Message爲中心,擴展接口爲Channel, Transporter, Client, Server, Codec。
  9. serialize,數據序列化層,可複用的一些工具,擴展接口爲Serialization, ObjectInput, ObjectOutput, ThreadPool。

二、層次關係

  1. 在RPC中,Protocol是核心層,也就是隻要有Protocol + Invoker + Exporter就能夠完成非透明的RPC調用,而後在Invoker的主過程上Filter攔截點。
  2. Consumer和Provider是抽象概念,只是想讓看圖者更直觀的瞭解哪些類分屬於客戶端與服務器端,不用Client和Server的緣由是Dubbo在不少場景下都使用Provider, Consumer, Registry, Monitor劃分邏輯拓普節點,保持統一律念。
  3. Cluster是外圍概念,因此Cluster的目的是將多個Invoker假裝成一個Invoker,這樣其它人只要關注Protocol層Invoker便可,加上Cluster或者去掉Cluster對其它層都不會形成影響,由於只有一個提供者時,是不須要Cluster的。
  4. Proxy層封裝了全部接口的透明化代理,而在其它層都以Invoker爲中心,只有到了暴露給用戶使用時,才用Proxy將Invoker轉成接口,或將接口實現轉成Invoker,也就是去掉Proxy層RPC是能夠Run的,只是不那麼透明,不那麼看起來像調本地服務同樣調遠程服務。
  5. Remoting實現是Dubbo協議的實現,若是你選擇RMI協議,整個Remoting都不會用上,Remoting內部再劃爲Transport傳輸層和Exchange信息交換層,Transport層只負責單向消息傳輸,是對Mina,Netty,Grizzly的抽象,它也能夠擴展UDP傳輸,而Exchange層是在傳輸層之上封裝了Request-Response語義。
  6. Registry和Monitor實際上不算一層,而是一個獨立的節點,只是爲了全局概覽,用層的方式畫在一塊兒。

三、模塊簡介

  1. dubbo-common 公共邏輯模塊,包括Util類和通用模型。
  2. dubbo-remoting 遠程通信模塊,至關於Dubbo協議的實現,若是RPC用RMI協議則不須要使用此包。
  3. dubbo-rpc 遠程調用模塊,抽象各類協議,以及動態代理,只包含一對一的調用,不關心集羣的管理。
  4. dubbo-cluster 集羣模塊,將多個服務提供方假裝爲一個提供方,包括:負載均衡, 容錯,路由等,集羣的地址列表能夠是靜態配置的,也能夠是由註冊中心下發。
  5. dubbo-registry 註冊中心模塊,基於註冊中心下發地址的集羣方式,以及對各類註冊中心的抽象。
  6. dubbo-monitor 監控模塊,統計服務調用次數,調用時間的,調用鏈跟蹤的服務。
  7. dubbo-config 配置模塊,是Dubbo對外的API,用戶經過Config使用Dubbo,隱藏Dubbo全部細節。
  8. dubbo-container 容器模塊,是一個Standlone的容器,以簡單的Main加載Spring啓動,由於服務一般不須要Tomcat/JBoss等Web容器的特性,不必用Web容器去加載服務。

四、依賴關係

提供方和消費方都是經過註冊中心來交互,提供方依賴註冊中心來暴露需提供的接口,服務方經過註冊中心來調用接口。提供方和註冊方與註冊中心之間是無狀態聯繫的,也就是說它倆不論說掛掉了不會影響另外一方的使用。這也是大部分生產/消費框架設計最科學的地方,雙方進行無狀態交互,互不干涉互不影響,軟件設計的觀察者模式也與此相似。網絡

 五、調用鏈

六、服務提供方提供服務的時序圖

 

七、服務消費方消費服務時序圖

3、實現細節

一、服務的解析

基於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轉換爲客戶端須要的接口。

4、總結

能夠看到引用配置對象ReferenceConfig的init方法調用Protocol的refer方法生成Invoker實例(如上圖中的紅色部分),這是服務消費的關鍵。接下來把Invoker轉換爲客戶端須要的接口。

一、dubbo的實現

Dubbo協議的Invoker轉爲Exporter發生在DubboProtocol類的export方法,它主要是打開socket偵聽服務,並接收客戶端發來的各類請求,通信細節由Dubbo本身實現。

二、RMI的實現:

RMI協議的Invoker轉爲Exporter發生在RmiProtocol類的export方法,
它經過Spring或Dubbo或JDK來實現RMI服務,通信細節這一塊由JDK底層來實現,這就省了很多工做量。

關於dubbo的設計還有筆者還有不少須要學習的地方,想學習更過的dubbo技術能夠去參考dubbo的官方API  http://dubbo.io/.

相關文章
相關標籤/搜索