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

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

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


Oreilly 對于微內(nèi)核架構(gòu)的定義是這樣的(純英文,大家要再三細(xì)品):
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)可以運(yùn)作的最小功能,有點(diǎn)像 MVP(Minimum Viable Product ,最小可用產(chǎn)品)。而插件模塊,則包含一些特殊處理邏輯、額外的功能、自定義代碼,用于強(qiáng)化和擴(kuò)展核心系統(tǒng),提供更多的業(yè)務(wù)能力。這么講還是比較抽象,所以,接下來,進(jìn)入主題,來看看 Dubbo 這個(gè) RPC 框架,是如何基于微內(nèi)核架構(gòu)進(jìn)行設(shè)計(jì)的。什么是 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ì)上是在解決如何進(jìn)行遠(yuǎn)程調(diào)用(rpc)的問題,通常一個(gè) rpc 系統(tǒng)都長這個(gè)樣子:


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

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

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


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

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

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

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


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

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

授人以魚不如授人以漁,其實(shí)這句古話是有出處的:
臨河而羨魚,不如歸家織網(wǎng)?!?《淮南子·說林訓(xùn)》人類歷史上迸發(fā)過許多璀璨的思想,就像微內(nèi)核架構(gòu)其實(shí)來源于操作系統(tǒng)的微內(nèi)核。我們在回過頭去看的時(shí)候,可以嘲笑他們有些觀念落伍了,但不要忘了一件事,慢一點(diǎn),再慢一點(diǎn),不要錯(cuò)過一些可能閃耀出來的那點(diǎn)星光。參考:
Microkernel Architecture
- Microkernel
- 微內(nèi)核架構(gòu)詳解
- Dubbo 框架設(shè)計(jì)
- Dubbo 擴(kuò)展點(diǎn)重構(gòu)
各類知識(shí)點(diǎn)總結(jié)
下面的文章都有對應(yīng)的原創(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 免費(fèi)領(lǐng)取原創(chuàng)思維導(dǎo)圖、精美PDF。在公眾號(hào)回復(fù)「888」領(lǐng)取,PDF內(nèi)容純手打有任何不懂歡迎來問我。
原創(chuàng)電子書
原創(chuàng)思維導(dǎo)圖

![]() |
|


