(一)前言
因?yàn)楣究蚣苁褂昧薲ubbo作為RPC框架铅乡,所以律秃,對于dubbo進(jìn)行相應(yīng)的學(xué)習(xí)外潜,通過官網(wǎng)的學(xué)習(xí),源碼的閱讀箕肃,總結(jié)出以下的內(nèi)容,希望對dubbo有個(gè)更全面的認(rèn)識今魔,同時(shí)會后續(xù)的使用勺像,后續(xù)的源碼閱讀有更好的幫助障贸。
(二 )RPC簡介
RPC(Remote Produce Call)遠(yuǎn)程過程調(diào)用,就是客戶端基于某種協(xié)議通過網(wǎng)絡(luò)向服務(wù)提供端請求服務(wù)處理吟宦,然后返回?cái)?shù)據(jù)篮洁。
對于客戶端來講,就和調(diào)用本地服務(wù)一樣督函,對開發(fā)人員是透明的嘀粱,不需要了解具體底層網(wǎng)絡(luò)傳輸協(xié)議。就是將本地調(diào)用的處理過程放在遠(yuǎn)程的機(jī)器上辰狡,而不是本地服務(wù)代理來處理锋叨。
套用到多線程的概念,其實(shí)RPC就是服務(wù)器間不同進(jìn)程之間通信協(xié)作的調(diào)用方式宛篇。
RPC的前身是RMI(Remote Method Call)娃磺,這是在jdk1.2的時(shí)候提出的。
RPC的基本組成部分Invoker叫倍、protocol偷卧、remote這三個(gè)組成部分,能夠完成一次完整的RPC調(diào)用
(三)dubbo微內(nèi)核設(shè)計(jì)機(jī)制
微內(nèi)核架構(gòu)核心系統(tǒng)設(shè)計(jì)時(shí)的兩個(gè)關(guān)鍵點(diǎn):
- 對問題域的核心概念吆倦、流程听诸、功能的洞察與抽象;有了這些核心元素蚕泽,plugin的擴(kuò)展才能有所依附晌梨、與其代碼之間的互動(dòng)才能實(shí)際落地發(fā)生;
- 設(shè)計(jì)一套機(jī)制用于規(guī)范和管理plugin生命周期:定義须妻、加載仔蝌、銷毀等;
Dubbo 的微內(nèi)核是廣義上的荒吏,它的思想是:核心系統(tǒng)+插件
敛惊。
這個(gè)微內(nèi)核說白了就是把不變的功能抽象出來稱為核心,把變動(dòng)的功能作為插件來擴(kuò)展绰更,符合開閉原則瞧挤,更容易擴(kuò)展、維護(hù)儡湾。
所以在后面的框架設(shè)計(jì)模塊和源碼中看到了大量的SPI插件皿伺。
當(dāng)然,在使用了足夠久之后盒粮,海量的插件管理也是一個(gè)值得思考的問題鸵鸥。
(四)dubbo其他概念
- 注冊中心、服務(wù)提供者、服務(wù)消費(fèi)者通過長連接進(jìn)行通信妒穴,monitor不是宋税。
- 注冊中心僅提供目錄服務(wù),不轉(zhuǎn)發(fā)請求讼油。
- 注冊中心數(shù)據(jù)庫宕機(jī)杰赛,仍能提供目錄服務(wù),但是不能注冊新服務(wù)矮台。
- 注冊中心宕機(jī)乏屯,不影響服務(wù)提供端和消費(fèi)端,可以通過本地緩存通訊瘦赫。
- 服務(wù)提供端宕機(jī)辰晕,消費(fèi)者會無限次重連等待服務(wù)提供者恢復(fù)。(后續(xù)可附錄代碼确虱。)
(五)dubbo框架設(shè)計(jì)
以下摘自dubbo官網(wǎng)開發(fā)指南中框架設(shè)計(jì)部分含友。文章鏈接
整體設(shè)計(jì)
圖例說明:
- 圖中左邊淡藍(lán)背景的為服務(wù)消費(fèi)方使用的接口,右邊淡綠色背景的為服務(wù)提供方使用的接口校辩,位于中軸線上的為雙方都用到的接口窘问。
- 圖中從下至上分為十層,各層均為單向依賴宜咒,右邊的黑色箭頭代表層之間的依賴關(guān)系惠赫,每一層都可以剝離上層被復(fù)用,其中故黑,Service 和 Config 層為 API汉形,其它各層均為 SPI。
- 圖中綠色小塊的為擴(kuò)展接口倍阐,藍(lán)色小塊為實(shí)現(xiàn)類,圖中只顯示用于關(guān)聯(lián)各層的實(shí)現(xiàn)類逗威。
- 圖中藍(lán)色虛線為初始化過程峰搪,即啟動(dòng)時(shí)組裝鏈,紅色實(shí)線為方法調(diào)用過程凯旭,即運(yùn)行時(shí)調(diào)時(shí)鏈概耻,紫色三角箭頭為繼承,可以把子類看作父類的同一個(gè)節(jié)點(diǎn)罐呼,線上的文字為調(diào)用的方法鞠柄。
針對上圖:總結(jié)出一個(gè)調(diào)用流程,在client端發(fā)起調(diào)用嫉柴,通過本地interface厌杜,通過已經(jīng)從Config中獲取的配置,通過ProxyFactory工廠動(dòng)態(tài)代理生成Proxy,訪問集群中的invoker(在調(diào)用之前夯尽,已經(jīng)完成了客戶端瞧壮、服務(wù)的服務(wù)注冊相關(guān),當(dāng)然匙握,Cluster也可以沒有咆槽,client可以直接調(diào)用配置好的路徑直接訪問,也就是單機(jī)使用場景)圈纺,invoker通過路由選擇秦忿,負(fù)載均衡算法,透明的獲取invoker蛾娶,然后通過配置的協(xié)議(此時(shí)灯谣,將一些信息寫入monitor中),將同步轉(zhuǎn)為異步茫叭,本地await酬屉,等待遠(yuǎn)程調(diào)用結(jié)果返回。將訪問請求序列化揍愁、通過網(wǎng)絡(luò)(mina呐萨、netty)訪問其他進(jìn)程(同服務(wù)器或者遠(yuǎn)程服務(wù)器)的具體方法。
各層說明
框架分層架構(gòu)中莽囤,各個(gè)層次的設(shè)計(jì)要點(diǎn):
- 服務(wù)接口層(Service):該層是與實(shí)際業(yè)務(wù)邏輯相關(guān)的谬擦,根據(jù)服務(wù)提供方和服務(wù)消費(fèi)方的業(yè)務(wù)設(shè)計(jì)對應(yīng)的接口和實(shí)現(xiàn)。
- 配置層(Config):對外配置接口朽缎,以
ServiceConfig
,ReferenceConfig
為中心惨远,可以直接初始化配置類,也可以通過 spring 解析配置生成配置類话肖。 - 服務(wù)代理層(Proxy):服務(wù)接口透明代理北秽,生成服務(wù)的客戶端
Stub
和服務(wù)器端Skeleton
(對應(yīng)RMI中的概念), 以ServiceProxy
為中心,擴(kuò)展接口為ProxyFactory
最筒。 - 注冊中心層(Registry):封裝服務(wù)地址的注冊與發(fā)現(xiàn)贺氓,以服務(wù) URL 為中心,擴(kuò)展接口為
RegistryFactory
,Registry
,RegistryService
床蜘。 - 路由層(Cluster):封裝多個(gè)提供者的路由及負(fù)載均衡辙培,并橋接注冊中心,以
Invoker
為中心邢锯,擴(kuò)展接口為Cluster
,Directory
,Router
,LoadBalance
扬蕊。 - 監(jiān)控層(Monitor):RPC 調(diào)用次數(shù)和調(diào)用時(shí)間監(jiān)控,以
Statistics
為中心丹擎,擴(kuò)展接口為MonitorFactory
,Monitor
,MonitorService
尾抑。 - 遠(yuǎn)程調(diào)用層(Protocol):封裝 RPC 調(diào)用,以
Invocation
,Result
為中心,擴(kuò)展接口為Protocol
,Invoker
,Exporter
蛮穿。 - 信息交換層(Exchange):封裝請求響應(yīng)模式庶骄,同步轉(zhuǎn)異步,以
Request
,Response
為中心践磅,擴(kuò)展接口為Exchanger
,ExchangeChannel
,ExchangeClient
,ExchangeServer
单刁。 - 網(wǎng)絡(luò)傳輸層(Transport):抽象
mina
和netty
為統(tǒng)一接口,以Message
為中心府适,擴(kuò)展接口為Channel
,Transporter
,Client
,Server
,Codec
羔飞。 - 數(shù)據(jù)序列化層(Serialize):可復(fù)用的一些工具,擴(kuò)展接口為
Serialization
,ObjectInput
,ObjectOutput
,ThreadPool
檐春。
關(guān)系說明
- 在
RPC
中逻淌,Protocol
是核心層,也就是只要有Protocol
+Invoker
+Exporter
就可以完成非透明的RPC
調(diào)用疟暖,然后在Invoker
的主過程上Filter
攔截點(diǎn)卡儒。 - 圖中的
Consumer
和Provider
是抽象概念,只是想讓看圖者更直觀的了解哪些類分屬于客戶端與服務(wù)器端俐巴,不用Client
和Server
的原因是Dubbo
在很多場景下都使用Provider
,Consumer
,Registry
,Monitor
劃分邏輯拓普節(jié)點(diǎn)骨望,保持統(tǒng)一概念。 - 而
Cluster
是外圍概念欣舵,所以Cluster
的目的是將多個(gè)Invoker
偽裝成一個(gè)Invoker
擎鸠,這樣其它人只要關(guān)注Protocol
層Invoker
即可,加上Cluster
或者去掉Cluster
對其它層都不會造成影響缘圈,因?yàn)橹挥幸粋€(gè)提供者時(shí)劣光,是不需要Cluster
的。 -
Proxy
層封裝了所有接口的透明化代理糟把,而在其它層都以Invoker
為中心绢涡,只有到了暴露給用戶使用時(shí),才用Proxy
將Invoker
轉(zhuǎn)成接口遣疯,或?qū)⒔涌趯?shí)現(xiàn)轉(zhuǎn)成Invoker
雄可,也就是去掉Proxy
層RPC
是可以Run
的,只是不那么透明另锋,不那么看起來像調(diào)本地服務(wù)一樣調(diào)遠(yuǎn)程服務(wù)。 - 而
Remoting
實(shí)現(xiàn)是Dubbo
協(xié)議的實(shí)現(xiàn)狭归,如果你選擇RMI
協(xié)議夭坪,整個(gè)Remoting
都不會用上,Remoting
內(nèi)部再劃為Transport
傳輸層和Exchange
信息交換層过椎,Transport
層只負(fù)責(zé)單向消息傳輸室梅,是對Mina
,Netty
,Grizzly
的抽象,它也可以擴(kuò)展UDP
傳輸,而Exchange
層是在傳輸層之上封裝了Request-Response
語義亡鼠。 -
Registry
和Monitor
實(shí)際上不算一層赏殃,而是一個(gè)獨(dú)立的節(jié)點(diǎn),只是為了全局概覽间涵,用層的方式畫在一起仁热。
模塊分包
-
dubbo-common
公共邏輯模塊:包括 Util 類和通用模型。 -
dubbo-remoting
遠(yuǎn)程通訊模塊:相當(dāng)于Dubbo
協(xié)議的實(shí)現(xiàn)勾哩,如果RPC
用RMI
協(xié)議則不需要使用此包抗蠢。 -
dubbo-rpc
遠(yuǎn)程調(diào)用模塊:抽象各種協(xié)議,以及動(dòng)態(tài)代理思劳,只包含一對一的調(diào)用迅矛,不關(guān)心集群的管理。 -
dubbo-cluster
集群模塊:將多個(gè)服務(wù)提供方偽裝為一個(gè)提供方潜叛,包括:負(fù)載均衡, 容錯(cuò)秽褒,路由等,集群的地址列表可以是靜態(tài)配置的威兜,也可以是由注冊中心下發(fā)销斟。 -
dubbo-registry
注冊中心模塊:基于注冊中心下發(fā)地址的集群方式,以及對各種注冊中心的抽象牡属。 -
dubbo-monitor
監(jiān)控模塊:統(tǒng)計(jì)服務(wù)調(diào)用次數(shù)票堵,調(diào)用時(shí)間的,調(diào)用鏈跟蹤的服務(wù)逮栅。 -
dubbo-config
配置模塊:是Dubbo
對外的API
悴势,用戶通過Config
使用Dubbo
,隱藏Dubbo
所有細(xì)節(jié)措伐。 -
dubbo-container
容器模塊:是一個(gè)Standlone
的容器特纤,以簡單的Main
加載Spring
啟動(dòng),因?yàn)榉?wù)通常不需要Tomcat/JBoss
等Web
容器的特性侥加,沒必要用Web
容器去加載服務(wù)捧存。
整體上按照分層結(jié)構(gòu)進(jìn)行分包,與分層的不同點(diǎn)在于:
-
container
為服務(wù)容器担败,用于部署運(yùn)行服務(wù)昔穴,沒有在層中畫出。 -
protocol
層和proxy
層都放在rpc
模塊中提前,這兩層是rpc
的核心吗货,在不需要集群也就是只有一個(gè)提供者時(shí),可以只使用這兩層完成rpc
調(diào)用狈网。 -
transport
層和exchange
層都放在remoting
模塊中宙搬,為rpc
調(diào)用的通訊基礎(chǔ)笨腥。 -
serialize
層放在common
模塊中,以便更大程度復(fù)用勇垛。
依賴關(guān)系
- 圖中小方塊
Protocol
,Cluster
,Proxy
,Service
,Container
,Registry
,Monitor
代表層或模塊脖母,藍(lán)色的表示與業(yè)務(wù)有交互,綠色的表示只對Dubbo
內(nèi)部交互闲孤。 - 圖中背景方塊
Consumer
,Provider
,Registry
,Monitor
代表部署邏輯拓?fù)涔?jié)點(diǎn)谆级。 - 圖中藍(lán)色虛線為初始化時(shí)調(diào)用,紅色虛線為運(yùn)行時(shí)異步調(diào)用崭放,紅色實(shí)線為運(yùn)行時(shí)同步調(diào)用哨苛。
- 圖中只包含
RPC
的層,不包含Remoting
的層币砂,Remoting
整體都隱含在Protocol
中建峭。
調(diào)用鏈
領(lǐng)域模型
-
Protocol
是服務(wù)域,它是Invoker
暴露和引用的主功能入口决摧,它負(fù)責(zé)Invoker
的生命周期管理亿蒸。 -
Invoker
是實(shí)體域,它是Dubbo
的核心模型掌桩,其它模型都向它靠擾边锁,或轉(zhuǎn)換成它,它代表一個(gè)可執(zhí)行體波岛,可向它發(fā)起invoke
調(diào)用茅坛,它有可能是一個(gè)本地的實(shí)現(xiàn),也可能是一個(gè)遠(yuǎn)程的實(shí)現(xiàn)则拷,也可能一個(gè)集群實(shí)現(xiàn)贡蓖。 -
Invocation
是會話域,它持有調(diào)用過程中的變量煌茬,比如方法名斥铺,參數(shù)等。