Dubbo的微內核機制

做者:劉昊旻 / 伯昊 / ludvik / haomin_liu(at)hotmail.comhtml


摘要

最近一直在思考蜂鳥物流系統中臺化可否引入微內核機制。做爲思考做業,首先把dubbo的微內核設計進行了總結沉澱。但願也對你們有用。java

本文藉由Dubbo採用微內核設計的原因做爲引子,簡單地探討了微內核架構Microkernel Architecture)設計實踐的思想。本文適合對Dubbo有必定使用經驗、並對其實現原理感興趣的同窗;也適合對微內核架構感興趣、並但願在本身的問題域中實踐的同窗。web

Wikipedia上微內核(Microkernel)的定義

In computer science, a microkernel (also known as μ-kernel) is the near-minimum amount of software that can provide the mechanisms needed to implement an operating system (OS). These mechanisms include low-level address space management, thread management, and inter-process communication (IPC). If the hardware provides multiple rings or CPU modes, the microkernel may be the only software executing at the most privileged level, which is generally referred to as supervisor or kernel mode. Traditional operating system functions, such as device drivers, protocol stacks and file systems, are typically removed from the microkernel itself and are instead run in user space. 數據庫

Monolithic vs. Microkernel

wikipedia上的定義特指這是一種操做系統內核設計風格,其對標的內核設計風格是monolithic kernel。apache

本文提到的微內核

本文講到的微內核架構(Microkernel architecture)更寬泛一些,不侷限於操做系統內核設計問題域,是一種設計範型design paradigm),更接近於《Software Architecture Patterns》一書中所寫:bootstrap

The microkernel architecture pattern allows you to add additional application features as plug-ins to the core application, providing extensibility as well as feature separation and isolation. 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. 緩存

Microkernel architecture pattern

微內核架構由兩大架構模塊組成:核心系統插件模塊。設計一個微內核體系關鍵工做所有集中於核心系統怎麼構建。ruby

全部的軟件存在的目的都是爲了去解決某個現實世界中具體領域的問題,簡稱問題域。好比dubbo的問題域是服務化與服務治理、maven的問題域是編譯打包與軟件項目管理性能優化

若是某個問題域發現有以下特徵,就能夠考慮使用微內核設計思想:bash

  1. 問題域可以沉澱一層比較核心的概念、流程或功能,這些元素能夠被穩定維護在一個核心之中;
    • Maven將代碼編譯打包場景定義爲三套生命週期:cleandefaultsite;其核心的default生命週期中20多個編譯步驟將問題域進行了高度抽象;Maven的plugin(又名mojo)在定義時都須要將本身掛載到某個goal和step上;
    • Dubbo將SOA調用高度抽象爲20餘個核心SPI,這些SPI又相似協議棧分層的設計細分爲核心的七、8個層次(proxyclusterprotocol等);dubbo將本身主要的SOA服務調用功能實現都定義爲這些SPI的具體擴展實現(plugin);有了這些抽象的SPI,plugin也就有了依附的基礎;
  2. 問題域有開放封閉的迫切需求,其中封閉的部分、可擴展部分分別由不一樣的團隊、工程來維護與組織。好比:
    • Framework的實現封閉 vs. 依賴Framework的應用擴展開放,好比dubbo這樣的中間件設計場景;
    • 操做系統核心實現封閉 vs. 操做系統應用層開放,好比全部微內核操做系統設計場景;
    • 平臺級業務系統核心邏輯實現封閉 vs. 具體業務系統擴展開放,好比阿里中臺核心平臺系統的設計場景;

上面的兩個問題域特徵,恰好帶出了在進行微內核架構核心系統設計時的兩個關鍵點:

  1. 對問題域的核心概念、流程、功能的洞察與抽象;有了這些核心元素,plugin的擴展才能有所依附、與其代碼之間的互動才能實際落地發生;
  2. 設計一套機制用於規範和管理plugin生命週期:定義加載銷燬等;

Dubbo架構概要介紹

Dubbo主要解決了服務化架構中的幾個關鍵問題:

  1. 遠程調用(RPC)
    • 解決遠程的進程到進程的調用;
  2. 集羣邏輯(cluster invoke cluster)
    • 更進一步,解決服務集羣到服務集羣的調用問題,例如軟負載機制;
  3. 服務發現與服務治理(Registry / Governance)
    • 集中解決服務治理所須要的基礎功能:服務的註冊與發現、註冊中內心的基礎服務治理功能

採用了相似協議棧的分層設計,概括下來主要分爲三層:

  1. Service層 (Service/Config/Proxy)
    • 解決provider側服務暴露 / consumer側消費服務的問題
  2. 集羣層(Registry / Cluster)
    • 解決服務註冊與發現、集羣調用策略領域關鍵問題
  3. RPC層(Protocol / Exchange/ Transport / Serialize)
    • 解決點到點的同步遠程調用領域的問題

這主要的三層符合分層架構風格的特徵,即: 上層邏輯無需關注下層實現細節。 這個特徵使得dubbo的擴展方能夠採用相似搭積木的方式進行擴展。好比:完全更換RPC協議,而共享上層的集羣調用與服務治理實現; 更多的奧妙就不在此文展開,感興趣的同窗能夠仔細研究下圖(摘自Dubbo官方文檔),內涵與細節很是豐富:

Dubbo分層架構

Dubbo與微內核架構

Dubbo爲何會使用微內核架構?最直觀的緣由:爲了推廣方便

Dubbo在設計之初,正值Alibaba B2B進行服務化轉型的關鍵時期。所要推廣的應用系統要麼還處於「恐龍級單體」應用狀態;要麼用「土辦法」解決簡單的集羣間調用。

想要順利推廣,得具有這幾個關鍵特徵:

  1. 性能好
    • 在一次服務調用中,框架所佔用的資源和時間要縮小到對應用層基本能夠忽略的程度;
  2. 魯棒性好
    • 各類設計細節都須要兜底和防呆,避免由於一些次要的緣由,致使整個應用系統崩潰(最經典的案例就是由於註冊中心bug致使服務的提供者被所有剔除惡性事件了,其中各類心酸,具體的心得能夠另開一篇文章專門探討);
  3. 引入的依賴少
    • 最小化對業務代碼的侵入:能夠作到應用容器無關(不一樣的web容器、homemade應用容器都不影響使用)、框架無關(不強依賴Spring)
  4. 可擴展性好(能作到開放封閉)
    • 依賴於本身抽象的SPI以及plugin加載機制,能作到應用方很是自由地經過SPI方式插入本身想要的邏輯,而不須要修改Dubbo自己

最後這一項,就是Dubbo採用微內核設計的主要緣由: dubbo所要支持的應用系統千差萬別,在一個組織中推行服務化,dubbo須要面臨諸多的擴展需求,舉幾個場景:

  • 場景一:

    • 遺留系統是Python寫的單體應用,想要用Java來進行領域拆分改造,有一些RPC調用的場景,老系統採用Rest + VIP的方式進行遠程調用;
  • 場景二:

    • 用戶想要實現本身的分佈式調用跟蹤,在這個基礎之上創建本身的運維工具體系。
  • 場景三:

    • 但願在SOA的調用鏈條上插入本身的filter邏輯,去實現調用審計的需求;

還有不少不一一列舉。做爲一個開源框架,嘗試將全部上面的需求都不加區分的在框架內實現必定是不可取的,衆口難調。

如何作到幹好本身的活兒,又不擋用戶的道兒呢?

答案不言自明。

Dubbo的擴展點實現舉例

以擴展實現Filter SPI爲例。

Filter SPI 定義:

package org.apache.dubbo.rpc;

import org.apache.dubbo.common.extension.SPI;

/** * Filter. (SPI, Singleton, ThreadSafe) */
@SPI
public interface Filter {

    /** * do invoke filter. * <p> * <code> * // before filter * Result result = invoker.invoke(invocation); * // after filter * return result; * </code> * * @param invoker service * @param invocation invocation. * @return invoke result. * @throws RpcException * @see org.apache.dubbo.rpc.Invoker#invoke(Invocation) */
    Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException;
}
複製代碼

filter是鏈式組裝的,要實現本身的filter邏輯,只須要實現下面的invoke接口便可。filter的組裝須要注意官方文檔中記錄的約定:

  • 用戶自定義 filter 默認在內置 filter 以後。
  • 特殊值 default,表示缺省擴展點插入的位置。好比:filter="xxx,default,yyy",表示 xxx 在缺省 filter 以前,yyy 在缺省 filter 以後。
  • 特殊符號 -,表示剔除。好比:filter="-foo1",剔除添加缺省擴展點 foo1。好比:filter="-default",剔除添加全部缺省擴展點。
  • provider 和 service 同時配置的 filter 時,累加全部 filter,而不是覆蓋。好比:<dubbo:provider filter="xxx,yyy"/> 和 <dubbo:service filter="aaa,bbb" />,則 xxx,yyy,aaa,bbb 均會生效。若是要覆蓋,需配置:<dubbo:service filter="-xxx,-yyy,aaa,bbb" />

擴展配置

<!-- 消費方調用過程攔截 -->
<dubbo:reference filter="xxx,yyy" />
<!-- 消費方調用過程缺省攔截器,將攔截全部reference -->
<dubbo:consumer filter="xxx,yyy"/>
<!-- 提供方調用過程攔截 -->
<dubbo:service filter="xxx,yyy" />
<!-- 提供方調用過程缺省攔截器,將攔截全部service -->
<dubbo:provider filter="xxx,yyy"/>
複製代碼

XxxFilter.Java

package com.xxx;
 
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
 
public class XxxFilter implements Filter {
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        // before filter ...
        Result result = invoker.invoke(invocation);
        // after filter ...
        return result;
    }
}
複製代碼

擴展實現Jar包Maven 項目結構:

src
 |-main
    |-java
        |-com
            |-xxx
                |-XxxFilter.java (實現Filter接口)
    |-resources
        |-META-INF
            |-dubbo
                |-com.alibaba.dubbo.rpc.Filter (純文本文件,內容爲:xxx=com.xxx.XxxFilter)
複製代碼

META-INF/dubbo/com.alibaba.dubbo.rpc.Filter:

xxx=com.xxx.XxxFilter
複製代碼

xxx就是com.xxx.XxxFilter全限定名的別名了,它會出如今dubbo的provider或者consumer的配置文件中,dubbo會按需加載組裝。

按照這樣的方式定義其餘的擴展點,以此類推,運行時dubbo會把自帶的、以及應用本身擴展的實現所有加載進來,以下圖所示(假設該應用還擴展了LoadBalance以及Protocol另外兩個擴展點):

dubbo-microkernel-example

Dubbo擴展點加載機制實現

擴展點加載

截取自dubbo官方文檔《開發者指南-擴展點加載》, Dubbo的擴展點加載由JDK 標準的 SPI (Service Provider Interface) 擴展點發現機制增強而來,主要針對這三個缺點:

  • JDK 標準的 SPI 會一次性實例化擴展點全部實現,若是有擴展實現初始化很耗時,但若是沒用上也加載,會很浪費資源。
  • 若是擴展點加載失敗,連擴展點的名稱都拿不到了。好比:JDK 標準的 ScriptEngine,經過 getName() 獲取腳本類型的名稱,但若是 RubyScriptEngine 由於所依賴的 jruby.jar 不存在,致使 RubyScriptEngine 類加載失敗,這個失敗緣由被吃掉了,和 ruby 對應不起來,當用戶執行 ruby 腳本時,會報不支持 ruby,而不是真正失敗的緣由。
  • 增長了對擴展點 IoC 和 AOP 的支持,一個擴展點能夠直接 setter 注入其它擴展點。

擴展點加載源代碼位於dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java

擴展點裝配

ServiceConfig.export()ReferenceConfig.refer()是dubbo bootstrap時組裝運行時擴展點的關鍵入口,能夠根據代碼順藤摸瓜。看代碼時可能會被各類xxxConfig搞暈,能夠參考dubbo官方文檔《開發者指南-實現細節

寫在後面

對於Dubbo來說,本文中描述的微內核機制足夠使用了。但對於上文中提到過的中臺業務系統而言,僅僅依靠核心系統+plugin加載機制又遠遠不夠。中臺業務系統面臨的是更爲嚴苛的工程挑戰:

  • 當擴展點SPI定義上千,如何治理?
  • 如何作到複雜業務流程配置所見即所得?
  • 中臺系統修改以後,如何作到對現有業務系統不影響?

這些問題,阿里中臺的星環系統都給出了本身答案,不得不佩服阿里中臺戰略堅決推動的勇氣以及其實現者的智慧。




餓了麼蜂鳥物流招聘啦!

蜂鳥物流現急招資深Java工程師!

在這裏,你將可以深度參與行業領先的即時配送核心系統開發工做、瞭解餓了麼微服務架構,更可以在平常開發工做中深度踐行餓了麼多活的核心技術

歡迎有意象的同窗踊躍投遞簡歷! 簡歷投遞郵箱:wei.chensh@ele.me

崗位描述

職責

1. 負責物流業務系統相關的需求分析、代碼開發、代碼審查工做
2. 配合架構師、技術Leader確保業務系統技術產出質量,對系統可用性進行設計,代碼質量進行把控,確保系統穩定性等
複製代碼

崗位要求

1. 本科及以上學歷(985/211優先),紮實的計算機基礎
2. 有過複雜、高併發交易系統的架構設計和優化經驗,尤爲是深度參與過互聯網業務架構設計的優先,擁有和工做年限相稱的廣度和(或)深度
3. 3年及以上工做經驗,長期使用JAVA及開源框架進行項目開發,並有必定得項目管理經驗;深刻使用Java,熟悉掌握經常使用的Java類庫及框架,如多線程、併發處理、I/O與網絡通信,Spring、Mybatis等;有系統排障經驗,能夠快速排查定位問題
4. 至少對高併發、分佈式、緩存、jvm 調優、序列化、微服務等一個或多個領域有過研究,而且有相關實踐經驗
5. 熟悉 MySQL 應用開發,熟悉數據庫原理和經常使用性能優化技術,以及 NoSQL,Queue 的原理、使用場景以及限制。
6. 學習能力強,認真負責,對技術有熱情有渴望
7. 具有良好的分析解決問題能力,能獨立承擔任務
8. 具備良好的溝通、團隊協做、計劃和主動性思考的能力,在互聯網或業界有必定影響力公司的工做經驗者優先
複製代碼




閱讀博客還不過癮?

歡迎你們掃二維碼經過添加羣助手,加入交流羣,討論和博客有關的技術問題,還能夠和博主有更多互動

博客轉載、線下活動及合做等問題請郵件至 shadowfly_zyl@hotmail.com 進行溝通

相關文章
相關標籤/搜索