Dubbo SPI 概述

Dubbo 透過 SPI 機制提供非常彈性的擴充性

擴充設計理念

可擴充性是任何系統追求的目標,它同樣適用於 Dubbo。

什麼是可擴充性

可擴充性是一種設計理念,代表我們對未來的展望。我們希望基於現有的架構或設計,當未來某些方面發生變化時,我們可以以最小的變動來適應這種變化。

可擴充性的優點

可擴充性的優點主要體現在模組之間的解耦,符合開閉原則,即對擴充開放,對修改關閉。當系統新增新功能時,無需修改現有系統的結構和程式碼,只需新增一個擴充即可。

擴充實作

一般來說,系統會使用 Factory、IoC、OSGI 等來管理擴充(外掛)的生命週期。考慮到 Dubbo 的適用性,我不希望強依賴於 Spring 等 IoC 容器,而自己建構一個小型 IoC 容器又覺得有點過度設計,因此選擇最簡單的 Factory 方式來管理擴充(外掛)。在 Dubbo 中,所有內部實作和第三方實作都是平等的。

Dubbo 中的可擴充性

  • 平等对待第三方实现。在 Dubbo 中,所有内部实现和第三方实现都是平等的,用户可以根据自己的业务需求替换 Dubbo 提供的原生实现。
  • 每個擴充點只封裝一個變更因素,以最大程度地提高重用性。每個擴充點的實現者通常只關心一件事。如果使用者需要擴充,只需要擴充他們關心的擴充點,大大減少了使用者的工作負擔。

Dubbo 擴充功能特色

Dubbo 中的擴充能力是從 JDK 標準 SPI 擴充點發現機制增強而來的,它改進了 JDK 標準 SPI 的以下問題:

  • JDK 標準 SPI 會一次性實例化擴充點的所有實現。如果某個擴充實現初始化耗時,即使不被使用也會被載入,造成資源浪費。
  • 如果擴充點載入失敗,甚至無法取得擴充點的名稱。例如:JDK 標準 ScriptEngine,透過 getName() 取得腳本類型名稱,但如果 RubyScriptEngine 因為缺少 jruby 而載入 RubyScriptEngine 類別失敗,當使用者執行 ruby 腳本時,會回報 ruby 不支援,而不是真正的失敗原因。

基於 Dubbo 提供的擴充能力,使用者可以根據自身需求輕鬆擴充其他協議、過濾器、路由等。以下介紹 Dubbo 擴充能力的特性。

  • 按需載入。Dubbo 的擴充能力不會一次性實例化所有實現,而是隨著擴充類別的需要進行實例化,減少資源浪費。
  • 增加了擴充類別的 IOC 能力。Dubbo 的擴充能力不僅僅是發現擴充服務實現類別,而是在此基礎上更進一步。如果擴充類別的屬性依賴於其他物件,Dubbo 會自動完成依賴物件的注入功能。
  • 增加了擴充類別的 AOP 能力。Dubbo 的擴充能力會自動發現擴充類別的包裝類別 (Wrapper Class),完成包裝類別的建構,增強擴充類別的功能。
  • 具備動態選擇擴充實現的能力。Dubbo 擴充會根據參數在運行時動態選擇對應的擴充類別,提高了 Dubbo 的擴充性。
  • 擴充實現可排序。可以根據使用者需求指定擴充實現的執行順序。
  • 提供擴充點的 Adaptive 能力。此能力使得某些擴充類別在消費者端生效,某些擴充類別在提供者端生效。

從 Dubbo 擴充的設計目標來看,Dubbo 實現的一些特性,例如擴充實現的動態選擇、IOC、AOP 等,都能為使用者提供非常靈活的擴充能力。

Dubbo 擴充載入流程

Dubbo 載入擴充的整個流程如下:

//imgs/v3/concepts/extension-load.png

主要有 4 個步驟:

  • 讀取並解析設定檔
  • 快取所有擴充實現
  • 根據使用者執行的擴充名稱,實例化對應的擴充實現
  • 執行擴充實例屬性的 IOC 注入,並實例化擴充包裝類別,實現 AOP 功能

如何使用 Dubbo 的擴充能力進行擴充

以下以擴充協議為例,說明如何使用 Dubbo 提供的擴充能力擴充 Triple 協議。

(1) 在協議實現 jar 包中放置一個文字檔:META-INF/dubbo/org.apache.dubbo.remoting.api.WireProtocol

tri=org.apache.dubbo.rpc.protocol.tri.TripleHttp2Protocol

(2) 實現類別內容

@Activate
public class TripleHttp2Protocol extends Http2WireProtocol {
    //...
}

說明:Http2WireProtocol 實現了 WireProtocol 介面

(3) 在 Dubbo 設定模組中,每個擴充點都有對應的設定屬性或標籤,設定指定使用哪個擴充。例如:

<dubbo:protocol name="tri" />

從上述擴充步驟可以看出,使用者基本上是在黑盒下完成擴充。

Dubbo 擴充應用

Dubbo 的擴充能力非常靈活,在其自身功能的實現中無處不在。

//imgs/v3/concepts/extension-use.png

Dubbo 的擴展性使其能夠輕鬆地將 Dubbo 專案逐個拆分成子模組,實現熱插拔功能。使用者可以根據自身需求完全替換 Dubbo 的原生實現,以滿足自身的業務需求。

使用場景

  • 如果您需要自定義負載平衡策略,可以使用 Dubbo 的擴展性。
  • 如果您需要實現自定義註冊中心,可以使用 Dubbo 的擴展能力。
  • 如果您需要實現自定義過濾器,可以使用 Dubbo 的擴展能力。

Dubbo 擴展機制對內部實現和第三方實現一視同仁。更多使用場景,請參見 SPI 擴展實現


上次修改時間:2023 年 1 月 2 日:增強英文文件 (#1798) (95a9f4f6c1c)