你們想要的Dubbo,三歪搞來了
本文公眾號來源:柳樹的絮叨叨
作者:發(fā)型吃飯的柳樹
本文已收錄至我的GitHub
授人以魚,不如授之以漁,其實這句話說的不只是如何教人。
從另一個角度看這句話,我們在學一樣東西的時候,要找到這樣東西的”漁“是什么。
對于一項技術(shù)來說,它背后的設(shè)計思想,就是學習它的”漁“,對于 Dubbo,”漁“,是微內(nèi)核架構(gòu)。
首先,我們以「保險索賠」為例,了解下什么是微內(nèi)核架構(gòu)。
保險索賠保險索賠的規(guī)則往往很復雜,不同保險產(chǎn)品、不同地區(qū)的索賠規(guī)則可能都不一樣。舉個例子,假設(shè)在紐約州(NY),汽車擋風玻璃被巖石擊碎,是可以索賠的,但是在加利福尼亞州(CA)則不行。這時候如果直接把這個邏輯寫到代碼里去,就是這樣:
if (在紐約) {
if (被巖石擊碎) {
// 索賠...
}
} else if (在加利福尼亞) {
if (被巖石擊碎) {
// 不索賠...
}
}
而且保險規(guī)則可不只這一條,到時候?qū)懗鰜砭褪沁@樣:
if (在紐約) {
if (被巖石擊碎) {
// 索賠...
}
if (被隕石擊碎) {
// 索賠...
}
if (被流星擊碎) {
// 索賠...
}
// more and more...
} else if (在加利福尼亞) {
if (被巖石擊碎) {
// 不索賠...
}
if (被隕石擊碎) {
// 不索賠...
}
if (被流星擊碎) {
// 不索賠...
}
// more and more...
}
可以看到,我們把索賠規(guī)則的代碼耦合到了索賠的核心系統(tǒng)中:

這會帶來兩個問題:
修改索賠規(guī)則需要重新發(fā)布整個系統(tǒng)
索賠規(guī)則的改動可能會影響整個系統(tǒng),甚至導致整個系統(tǒng)不可用
于是我們把這些規(guī)則抽取出來,有個專門的地方去管理這些規(guī)則,簡單說,就是「解耦」:

不同州的規(guī)則還是放到一起的,而我們在索賠處理的時候,每次只需要加載一個州的索賠規(guī)則,不存在既需要紐約州的規(guī)則,又需要加州規(guī)則的情況:


Oreilly 對于微內(nèi)核架構(gòu)的定義是這樣的(純英文,大家要再三細品):
The microkernel architecture pattern consists of two types of architecture components: a core system and plug-in modules.
Application logic is divided between independent plug-in modules and the basic core system, providing extensibility, flexibility, and isolation of application features and custom processing logic.

The core system of the microkernel architecture pattern traditionally contains only the minimal functionality required to make the system operational.核心系統(tǒng)只包含讓系統(tǒng)可以運作的最小功能,有點像 MVP(Minimum Viable Product ,最小可用產(chǎn)品)。而插件模塊,則包含一些特殊處理邏輯、額外的功能、自定義代碼,用于強化和擴展核心系統(tǒng),提供更多的業(yè)務能力。這么講還是比較抽象,所以,接下來,進入主題,來看看 Dubbo 這個 RPC 框架,是如何基于微內(nèi)核架構(gòu)進行設(shè)計的。什么是 RPC 系統(tǒng)的 core?
The plug-in modules are stand-alone, independent components that contain specialized processing, additional features, and custom code that is meant to enhance or extend the core system to produce additional business capabilities.
Dubbo 在本質(zhì)上是在解決如何進行遠程調(diào)用(rpc)的問題,通常一個 rpc 系統(tǒng)都長這個樣子:


- 服務提供方,暴露服務時,只需要把自己注冊到一個 map 里
- 服務消費方,引用服務時,則只需從 map 里獲取到服務提供方的引用
- 當服務消費方調(diào)用服務提供方的方法時,其實是一次本地內(nèi)存調(diào)用,不涉及什么網(wǎng)絡(luò)傳輸、協(xié)議轉(zhuǎn)換、序列化、反序列化

我們從系統(tǒng)的角度,看看 Dubbo 的整體設(shè)計圖:

- proxy 層,解決的是:如何實現(xiàn)服務接口的透明代理;
- cluster 層,解決的是:當有多個服務提供者時,如何調(diào)用、如何負載均衡等等;
- 底下三層,也就是 remote 層,解決的是:如何進行遠程調(diào)用;
- …


- 當你只需要一次 injvm 的 rpc 調(diào)用時,只用 Protocol ,足矣;
- 如果你需要遠程調(diào)用,而且有多個服務提供方,那需要引入 remote、cluster 和 registry;
- 如果你還需要透明式的 rpc 調(diào)用,那就再引入 proxy 層
Protocol 層,其實就是上面提到的,一個最簡化的 rpc 模型:

- exporter:對應服務提供方,負責把服務暴露到某個地方
- invoker:對應服務消費方,從某個地方引用服務,并調(diào)用服務
- protocol:使用什么樣的 protocol,決定了會有什么樣的 invoker 和 exporter
injvm 協(xié)議,那就會生成 InjvmInvoker 和 InjvmExporter:

dubbo 協(xié)議,則會生成 DubboInvoker 和 DubboExporter:

dubbo 協(xié)議的 refer 方法,會把 invoker 放進一個 invokers 集合里,injvm 協(xié)議的 refer 方法,則直接 new 一個 invoker 后就返回了,說明前者是有可能存在多個服務提供者的,而后者只會有一個。
而這些細節(jié)上的差異,追溯到根源,就是你用了什么樣的協(xié)議(protocol)。
在 RPC 中,Protocol 是核心層,也就是只要有 Protocol + Invoker + Exporter 就可以完成非透明的 RPC 調(diào)用。—— from Dubbo 框架設(shè)計微內(nèi)核架構(gòu)的其他使用
除了上面提到的保險索賠、Dubbo,微內(nèi)核架構(gòu)還被用到很多地方。
其實微內(nèi)核架構(gòu)的起源,是操作系統(tǒng):
這里不展開講,大家可以前往維基百科了解下。后來,這種思想逐漸被演變成一種架構(gòu)設(shè)計模式,于是有了「微內(nèi)核架構(gòu)」。它被用在了許多客戶端應用,像 Chrome 瀏覽器:


Eclipse 也一樣,核心就是一個編輯器,和記事本沒什么區(qū)別,給它添加各種各樣的插件,像代碼高亮、java 代碼編譯等等,就成了一個好用的開發(fā)工具;第三方開發(fā)者同樣可以給它開發(fā)各種插件。之后它又被進一步用在了一些軟件框架、業(yè)務系統(tǒng)上,比如今天講到的 Dubbo 和保險索賠系統(tǒng)。甚至在之后的「六邊形架構(gòu)」、DDD 上,都可以看到「微內(nèi)核架構(gòu)」的影子,這兩種設(shè)計思想被大量用到各種框架、中間件的設(shè)計上,比如有贊的 MAXIM 全鏈路壓測引擎:

作為一種架構(gòu)設(shè)計的模式,通常都會考慮這些問題:
- 如何降低系統(tǒng)的復雜度
- 如何提高系統(tǒng)的可維護性
- 如何提高系統(tǒng)的可擴展性
- 如何提高系統(tǒng)的可配置性
- 核心系統(tǒng)和插件是低耦合的,插件可插拔
- 核心系統(tǒng)和插件之間是隔離的,改變也是隔離的
- 核心系統(tǒng)可以保持穩(wěn)定
- 插件可支持動態(tài)添加(熱部署)
- 插件可以獨立測試
- 大部分實現(xiàn)都是基于產(chǎn)品的(product based),實現(xiàn)時不會考慮高可伸縮性,當然這同樣取決于你的實現(xiàn)方式。
- 微內(nèi)核架構(gòu)需要深思熟慮的設(shè)計和契約的規(guī)劃管理,因此實現(xiàn)起來比較復雜。
- 契約的版本機制、插件的注冊機制、插件的粒度、插件連接方式的選擇都使得實現(xiàn)起來是復雜的。

授人以魚不如授人以漁,其實這句古話是有出處的:
臨河而羨魚,不如歸家織網(wǎng)。—— 《淮南子·說林訓》人類歷史上迸發(fā)過許多璀璨的思想,就像微內(nèi)核架構(gòu)其實來源于操作系統(tǒng)的微內(nèi)核。我們在回過頭去看的時候,可以嘲笑他們有些觀念落伍了,但不要忘了一件事,慢一點,再慢一點,不要錯過一些可能閃耀出來的那點星光。參考:
Microkernel Architecture
- Microkernel
- 微內(nèi)核架構(gòu)詳解
- Dubbo 框架設(shè)計
- Dubbo 擴展點重構(gòu)
各類知識點總結(jié)
下面的文章都有對應的原創(chuàng)精美PDF,在持續(xù)更新中,可以來找我催更~
- 92頁的Mybatis
- 129頁的多線程
- 141頁的Servlet
- 158頁的JSP
- 76頁的集合
- 64頁的JDBC
- 105頁的數(shù)據(jù)結(jié)構(gòu)和算法
- 142頁的Spring
- 58頁的過濾器和監(jiān)聽器
- 30頁的HTTP
- 42頁的SpringMVC
- Hibernate
- AJAX
- Redis
- ......
掃碼或者微信搜Java3y 免費領(lǐng)取原創(chuàng)思維導圖、精美PDF。在公眾號回復「888」領(lǐng)取,PDF內(nèi)容純手打有任何不懂歡迎來問我。
原創(chuàng)電子書
原創(chuàng)思維導圖

![]() |
|


