<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          你們想要的Dubbo,三歪搞來了

          共 5739字,需瀏覽 12分鐘

           ·

          2020-05-21 23:21

          本文公眾號來源:柳樹的絮叨叨

          作者:發(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)中:

          4584c943fe39bc78bdc35d0a8d1c85ea.webp

          這會帶來兩個問題:

          • 修改索賠規(guī)則需要重新發(fā)布整個系統(tǒng)

          • 索賠規(guī)則的改動可能會影響整個系統(tǒng),甚至導致整個系統(tǒng)不可用

          于是我們把這些規(guī)則抽取出來,有個專門的地方去管理這些規(guī)則,簡單說,就是「解耦」:

          1c574b42d714348d2658f117418a2f70.webp

          這樣就解決了「耦合度高」的問題,但其實解耦的還不夠徹底。
          不同州的規(guī)則還是放到一起的,而我們在索賠處理的時候,每次只需要加載一個州的索賠規(guī)則,不存在既需要紐約州的規(guī)則,又需要加州規(guī)則的情況

          3befa364c6e09d31969563d6498355c2.webp

          另外,如果后面新來了一個州,想接入索賠系統(tǒng),那么如何讓這個州,在不影響其他州的情況下,配置自己的索賠規(guī)則?于是有了這樣一套保險索賠的「微內(nèi)核架構(gòu)」:

          eb54b382709f81a6f08cbc4f2fe68d63.webp

          簡單說就是,這套系統(tǒng)分兩個模塊:1、中間的核心模塊處理保險索賠的基本業(yè)務邏輯;2、保險規(guī)則由每個州自己去實現(xiàn),做成插件,可以被單獨加載和移除,不影響核心系統(tǒng)和其他插件。了解完了保險索賠系統(tǒng)的微內(nèi)核實現(xiàn),我們再來看看微內(nèi)核架構(gòu),到底是什么。什么是微內(nèi)核架構(gòu)

          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 extensibilityflexibility, and isolation of application features and custom processing logic.

          5956f3ff993b4a8ccc4762b778044b76.webp

          簡單說,就是微內(nèi)核架構(gòu)包含兩個組件:核心系統(tǒng)(core system)插件模塊(plug-in modules),目的是為了擴展性、靈活性和隔離性。核心系統(tǒng)和插件模塊又都有什么職責呢?
          The core system of the microkernel architecture pattern traditionally contains only the minimal functionality required to make the system operational.
          The plug-in modules are stand-alone, independent components that contain specialized processingadditional features, and custom code that is meant to enhance or extend the core system to produce additional business capabilities.
          核心系統(tǒng)只包含讓系統(tǒng)可以運作的最小功能,有點像 MVP(Minimum Viable Product ,最小可用產(chǎn)品)。而插件模塊,則包含一些特殊處理邏輯、額外的功能、自定義代碼,用于強化和擴展核心系統(tǒng),提供更多的業(yè)務能力。這么講還是比較抽象,所以,接下來,進入主題,來看看 Dubbo 這個 RPC 框架,是如何基于微內(nèi)核架構(gòu)進行設(shè)計的。什么是 RPC 系統(tǒng)的 core?

          Dubbo 在本質(zhì)上是在解決如何進行遠程調(diào)用(rpc)的問題,通常一個 rpc 系統(tǒng)都長這個樣子:

          9b9094ea5d2491995cb96ca391d4067a.webp

          但是這些都是一個 rpc 系統(tǒng)所必須的嗎?能不能去掉哪個模塊后,依然可以進行 rpc 調(diào)用?相信大多數(shù)人都可以發(fā)現(xiàn),stub 層是可以去掉的,去掉后,無非你就沒法再進行透明式調(diào)用罷了。還有嗎?還有其他哪個模塊也可以去掉嗎?我們來看一個極簡的 rpc 調(diào)用:

          c7e79c183a2c19bb013f9ede240a014a.webp

          在這個例子里,服務提供方,和服務消費方,是位于同一塊內(nèi)存的:
          • 服務提供方,暴露服務時,只需要把自己注冊到一個 map 里
          • 服務消費方,引用服務時,則只需從 map 里獲取到服務提供方的引用
          • 當服務消費方調(diào)用服務提供方的方法時,其實是一次本地內(nèi)存調(diào)用,不涉及什么網(wǎng)絡(luò)傳輸、協(xié)議轉(zhuǎn)換、序列化、反序列化
          大道至簡,當我們把 rpc 這個模型進行簡化后,會發(fā)現(xiàn)其實這樣就足夠了:

          1818992505ae4dc242d8a41b24e46aac.webp

          其實這也是 Dubbo 里 inJVM 協(xié)議的實現(xiàn)原理。當然實際使用中,我們不可能只使用內(nèi)存調(diào)用的 rpc,舉這個例子,其實是為了下面介紹 Dubbo 的內(nèi)核。什么是 Dubbo 的 core?

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

          ad99a25e8b6fca9316f43671aaf52983.webp

          這個是一種傳統(tǒng)的分層視角,每一層都有自己要解決的問題,用 DDD 的話來說,就是每個域都有自己的問題空間:
          • proxy 層,解決的是:如何實現(xiàn)服務接口的透明代理;
          • cluster 層,解決的是:當有多個服務提供者時,如何調(diào)用、如何負載均衡等等;
          • 底下三層,也就是 remote 層,解決的是:如何進行遠程調(diào)用;
          按照這個視角來看,其實每一層都有自己的 core,每一層都支持通過 SPI 的方式,來實現(xiàn)擴展。但如果我們換個視角來看,之前說過,Dubbo 本質(zhì)上是為了解決 rpc 的問題,那么其實我們只需要 protocol 層就足夠了:

          576fbcbced832817f3a0eb70e54da5be.webp

          我們也不必再用傳統(tǒng)的分層架構(gòu)來看,而是換一個視角:

          4b26d41075c78d44fe52057997e96041.webp

          這個叫「六邊形架構(gòu)」(Hexagonal Architecture),也叫「端口-適配器架構(gòu)」(Ports and Adapters Architecture),這里就不展開細講了,有興趣的同學可以谷歌下。兩種視角的不同就在于,傳統(tǒng)分層視角沒有突出核心和重點,你看不出哪一層是必須的,哪一層是整個架構(gòu)的起源,而六邊形架構(gòu),則一目了然。對于 Dubbo 來說,只有 Protocol 層是核心,是必須的:
          • 當你只需要一次 injvm 的 rpc 調(diào)用時,只用 Protocol ,足矣;
          • 如果你需要遠程調(diào)用,而且有多個服務提供方,那需要引入 remote、cluster 和 registry;
          • 如果你還需要透明式的 rpc 調(diào)用,那就再引入 proxy 層
          那么 Protocol 層都做了什么呢,為什么有了它就可以實現(xiàn)一次 rpc 調(diào)用?Protocol 層如何實現(xiàn) rpc 調(diào)用?

          Protocol 層,其實就是上面提到的,一個最簡化的 rpc 模型:

          c4cd114afc643e83bd16026f9a0810ae.webp

          三個角色:
          • exporter:對應服務提供方,負責把服務暴露到某個地方
          • invoker:對應服務消費方,從某個地方引用服務,并調(diào)用服務
          • protocol:使用什么樣的 protocol,決定了會有什么樣的 invoker 和 exporter
          很明顯,核心角色是 protocol,比如你采用 injvm 協(xié)議,那就會生成 InjvmInvoker 和 InjvmExporter:

          d620e85b498fd633611fd4a80dbd2aeb.webp

          而如果你采用的是 dubbo 協(xié)議,則會生成 DubboInvoker 和 DubboExporter:

          22332881520ad822fcb30374b94ca772.webp

          仔細看代碼,你會發(fā)現(xiàn),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):

          8bf32edf6057ed13177e367b45d8760c.webp

          左邊是 Microkernel,右邊是與之對應的 Monolithic Kernel,前者只提供最最基礎(chǔ)的操作系統(tǒng)能力,而把更多的能力開放給外界來提供,而后者則傾向于提供一個大而全的操作系統(tǒng)。
          這里不展開講,大家可以前往維基百科了解下。后來,這種思想逐漸被演變成一種架構(gòu)設(shè)計模式,于是有了「微內(nèi)核架構(gòu)」。它被用在了許多客戶端應用,像 Chrome 瀏覽器:

          e3d73f97ea58cedcb90c9676dce93cca.webp

          Eclipse 編輯器:

          dce3fab79e0795b85640b6e383a52b78.webp

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

          1e79166f6d6ca9312dbc73a5e9fe5bfe.webp

          你可以用一兩句話概況這種思想,比如:開閉原則、模板模式、把不變的和變化的隔離等等,但是僅僅通過這種標簽式的、高濃縮的、刻板印象的語言就來概況它,未免還是太過缺乏細節(jié)和激情了。微內(nèi)核架構(gòu)的優(yōu)缺點

          作為一種架構(gòu)設(shè)計的模式,通常都會考慮這些問題:

          • 如何降低系統(tǒng)的復雜度
          • 如何提高系統(tǒng)的可維護性
          • 如何提高系統(tǒng)的可擴展性
          • 如何提高系統(tǒng)的可配置性
          微內(nèi)核架構(gòu)也不例外,它的優(yōu)點很明顯:擴展性:高
          • 核心系統(tǒng)和插件是低耦合的,插件可插拔
          健壯性:高
          • 核心系統(tǒng)和插件之間是隔離的,改變也是隔離的
          • 核心系統(tǒng)可以保持穩(wěn)定
          易部署性:高
          • 插件可支持動態(tài)添加(熱部署)
          可測試性:高
          • 插件可以獨立測試
          缺點也有:可伸縮性:低
          • 大部分實現(xiàn)都是基于產(chǎn)品的(product based),實現(xiàn)時不會考慮高可伸縮性,當然這同樣取決于你的實現(xiàn)方式。
          開發(fā)難度:高
          • 微內(nèi)核架構(gòu)需要深思熟慮的設(shè)計和契約的規(guī)劃管理,因此實現(xiàn)起來比較復雜。
          • 契約的版本機制、插件的注冊機制、插件的粒度、插件連接方式的選擇都使得實現(xiàn)起來是復雜的。
          開發(fā)難度高這一點,從 Dubbo 的擴展點重構(gòu)歷程就可以看出來,其實一開始 Dubbo 并不是我們看到的分層架構(gòu),而是一步一步演進過來的,每一步都包含這背后開發(fā)人員的臥薪嘗膽和絞盡腦汁:

          149d660c391dcde21489c29b9aaaaf91.webp

          最后

          授人以魚不如授人以漁,其實這句古話是有出處的:

          臨河而羨魚,不如歸家織網(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ù)更新中,可以來找我催更~

          掃碼或者微信搜Java3y 免費領(lǐng)取原創(chuàng)思維導圖、精美PDF。在公眾號回復「888」領(lǐng)取,PDF內(nèi)容純手打有任何不懂歡迎來問我。


          
           

          原創(chuàng)電子書
          2886e4c7bb0d2c7e5d415741d3ade3f7.webp

          原創(chuàng)思維導圖

          5447ee8c0d4caacc355f1b99867e0ce2.webp


          a00b135a34a892f996bcf9fafa8df566.webp

          1dd1f2fa4e2c8cc48e0c5570cbc8b3ca.webp

          1dd1f2fa4e2c8cc48e0c5570cbc8b3ca.webp

          瀏覽 111
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本黄色小视频 | 欧美爱爱一区 | 亚洲视频网站在线 | 啪啪啪网站免费观看 | 日韩有码第一页 |