螞蟻金服 SOFAArk 0.6.0 新特性介紹 | 模組化開發容器

螞蟻金服分散式架構發表於2019-03-21

SOFAStack

Scalable Open Financial Architecture Stack 是螞蟻金服自主研發的金融級分散式架構,包含了構建金融級雲原生架構所需的各個元件,是在金融場景裡錘鍊出來的最佳實踐。


螞蟻金服在 SOFAStack 體系內研發了一款基於 Java 實現的輕量級類隔離容器,主要提供類隔離和應用(模組)合併部署能力--SOFAArk。本篇文章為 SOFAArk 0.6.0 的新特性介紹。

GitHub 地址:github.com/alipay/sofa…

簡介

在大型軟體開發過程中,通常會推薦底層功能外掛化、業務功能模組化的開發模式,以其達到低耦合、高內聚、功能複用的優點。基於此,SOFAArk 提供了一套較為規範化的外掛化、模組化開發方案,產品能力主要包括:

  • 定義外掛開發規範,提供 Maven 打包工具,簡單快速將多個二方包打包成外掛(Ark Plugin,以下簡稱 Plugin), 適用於將底層元件外掛化輸出,例如 RPC、富客戶端等;
  • 定義模組開發規範,提供 Maven 打包工具,簡單快速將應用(Spring Boot/SOFABoot/普通 Java 應用)打包成模組 (Ark Biz,以下簡稱 Biz),適用於將業務元件模組化輸出,提升業務能力複用;
  • 定義類載入模型,執行時 Plugin、Biz 之間均相互隔離,執行時由不同的 ClassLoader 載入,有效避免相互之間的包衝突,降低 Plugin 和 Biz 對執行環境的要求;
  • 定義標準的程式設計介面,包括服務、事件、擴充套件點等機制,方便 Plugin、Biz 互動和擴充套件;
  • 定義業務模組 (Biz) 生命週期,支援多 Biz 合併部署。開發階段將多個 Biz 打包成 Executable Ark Jar 包(以下簡稱 Ark 包),或者執行時使用 API 或配置中心(Zookeeper)動態地管理 Biz 安裝和解除安裝,滿足多應用合併部署及動態升級的需求。

基於以上能力,SOFAArk 可以幫助解決多應用(模組)合併部署、動態升級、依賴包衝突等場景問題。

場景

場景一:合併部署

複雜專案通常需要跨團隊協作開發,各自負責不同的元件。協調跨團隊合作開發會遇到不少問題:比如各自技術棧不統一導致的依賴衝突、往同一個 Git 倉庫提交程式碼常常導致 merge 衝突、元件功能相互依賴影響測試進度。因此,如果能讓每個團隊將負責的功能元件當成一個個單獨的應用開發和測試,執行時合併部署,那麼將有助於提升開發效率及應用可擴充套件性。

SOFAArk 提出了一種特殊的包結構 -- Ark Biz,使用者可以使用 Maven 外掛將應用打包成 Biz,允許多 Biz 在 SOFAArk 容器之上合併部署,並通過統一的程式設計介面互動,如下:

螞蟻金服 SOFAArk 0.6.0 新特性介紹 | 模組化開發容器

Biz 對應用型別沒有限制,可以是 Spring Boot/SOFABoot/Java 普通應用型別,Biz 之間採用統一的程式設計介面-SOFA JVM服務進行互動。釋出和引用服務也非常簡單,使用 API 或者 Spring 註解/XML 方式:

螞蟻金服 SOFAArk 0.6.0 新特性介紹 | 模組化開發容器

合併部署的形式,分為兩種 -- 靜態合併部署和動態合併部署。

靜態合併部署

在開發階段,應用可以將其他應用打成的 Biz 包通過 Maven 依賴的方式引入,而當自身被打成 Ark 包時,會將引入的其他 Biz 包一併打入。通過 java -jar 啟動 Ark 包時,則會根據優先順序依次啟動各 Biz,單個 Biz 使用獨立的 BizClassLoader 載入,不需要考慮依賴包衝突問題,Biz 之間則通過 SOFA JVM 服務互動。

動態合併部署

動態合併部署區別於靜態合併部署最大的一點是,在執行時可以通過 API 或者配置中心(Zookeeper)來控制 Biz 的部署和解除安裝。動態合併部署的設計理念圖如下:

螞蟻金服 SOFAArk 0.6.0 新特性介紹 | 模組化開發容器

無論是靜態抑或動態合併部署都有存在宿主應用 (master biz) 的概念,如果 Ark 包只打包了一個 Biz,則該 Biz 預設成為宿主應用;如果 Ark 包打包了多個 Biz 包,需要配置指定宿主應用。宿主 Biz 和其他 Biz 唯一不同在於,宿主 Biz 不允許被解除安裝。

一般而言,宿主應用會作為流量入口的中臺系統,具體的服務實現會放在不同的動態 Biz 中,供宿主應用呼叫。宿主應用可以使用 SOFAArk 提供的客戶端 API 實現動態應用的部署和解除安裝。除了 API, SOFAArk 提供了 Config Plugin,用於對接配置中心(目前支援 Zookeeper),執行時接受動態配置;Config Plugin 會解析下發的配置,控制動態應用的部署和解除安裝。

場景二:動態升級

SOFAArk 在螞蟻內部也被用來解決動態升級的場景問題。有時候,因為業務迭代較快,應用依賴的某二方包需要頻繁的變更,這將導致應用每次都因為升級二方包版本做變更釋出,影響開發效率;而作為二方包的開發者,常常因為推動依賴方應用升級阻力較大,導致新特性無法按時上線,影響業務發展。

為了加快創新業務的迭代速度,會將需要頻繁變更的二方包打包成 Biz 包,供其他應用依賴。作為依賴方,不會直接在 Pom 檔案(假設是使用 Maven 構建)定義 Biz 包版本,而是通過配置中心(例如 Zookeeper)下發配置。如此,當應用啟動時,會拉取 Biz 版本配置資訊,進而拉取正確版本的 Biz 包並啟動。如此,當需要依賴方升級 Biz 版本時,只需要在配置中心重新推送配置即可。

場景三:依賴隔離

日常使用 Java 開發,常常會遇到包依賴衝突的問題,尤其當應用變得臃腫龐大,包衝突的問題也會變得更加棘手,導致各種各樣的報錯,例如 LinkageError, NoSuchMethodError 等。實際開發中,可以採用多種方法來解決包衝突問題,比較常見的是類似 Spring Boot 的做法:統一管理應用所有依賴包的版本,保證這些三方包不存在依賴衝突。這種做法只能有效避免包衝突問題,不能根本上解決包衝突的問題。如果某個應用的確需要在執行時使用兩個相互衝突的包,例如 protobuf2 和 protobuf3,那麼類似 Spring Boot 的做法依然解決不了問題。

為了徹底解決包衝突的問題,需要藉助類隔離機制,使用不同的 ClassLoader 載入不同版本的三方依賴,進而隔離包衝突問題。 OSGi 作為業內最出名的類隔離框架,自然是可以被用於解決上述包衝突問題,但是 OSGi 框架門檻較高,功能繁雜。為了解決包衝突問題,引入 OSGi 框架,有牛刀殺雞之嫌,反而使工程變得更加複雜,不利於開發。

SOFAArk 採用輕量級的類隔離方案來解決日常經常遇到的包衝突問題,在螞蟻金服內部服務於整個 SOFABoot 技術體系,彌補 Spring Boot 沒有的類隔離能力。SOFAArk 提出了一種特殊的包結構 -- Ark Plugin,在遇到包衝突時,使用者可以使用 Maven 外掛將若干衝突包打包成 Plugin,執行時由獨立的 PluginClassLoader 載入,從而解決包衝突。

假設如下場景,如果工程需要引入兩個三方包:A 和 B,但是 A 需要依賴版本號為 0.1 的 C 包,而恰好 B 需要依賴版本號為 0.2 的 C 包,且 C 包的這兩個版本無法相容:

螞蟻金服 SOFAArk 0.6.0 新特性介紹 | 模組化開發容器

此時,即可使用 SOFAArk 解決該依賴衝突問題:只需要把 A 和版本為 0.1 的 C 包一起打包成一個 Ark 外掛,然後讓應用工程引入該外掛依賴即可。

不僅僅是在出現依賴包衝突時,可以通過打包 Ark Plugin 解決,對於複雜的底層元件,例如 RPC 元件,為了防止它和依賴方應用存在包衝突,常會將 RPC 或其他中介軟體元件單獨打成 Plugin 輸出。

其次,Ark Plugin 也被用於擴充套件 SOFAArk 容器能力,例如 runtime-sofa-boot-plugin 用於提供 SOFA JVM 服務通訊能力; web-ark-plugin 用於提供多 web 應用合併部署能力等。

原理

在介紹完 SOFAArk 的使用場景之後,我們簡單介紹其類載入模型。SOFAArk 包含三個概念,Ark Container, Ark Plugin 和 Ark Biz; 執行時邏輯結構圖如下:

螞蟻金服 SOFAArk 0.6.0 新特性介紹 | 模組化開發容器

在介紹這三個概念之前,先介紹 Executable Ark Jar 包概念:Ark 包是 SOFAArk 定義的特殊格式的可執行 Jar 包。SOFAArk 提供的 Maven 外掛 sofa-ark-maven-plugin 可以將單個或多個 Biz打包成 Ark 包,使用 java -jar命令即可在 SOFAArk 容器之上啟動所有應用。Ark 包通常包含 Ark Container、Ark Plugin 和 Ark Biz。下面是一個簡單的 Ark 包工程目錄:

螞蟻金服 SOFAArk 0.6.0 新特性介紹 | 模組化開發容器

可以很直觀的看到 Ark Container、Ark Plugin 和 Ark Biz 在 Ark 包的組織形式中。針對這三個概念我們簡單做下名詞解釋:

  • Ark Container: SOFAArk 容器,負責 Ark 包啟動執行時的管理。Plugin 和 Biz 執行在 SOFAArk 容器之上,容器具備管理外掛和應用的功能,容器啟動成功後會自動解析 classpath 包含的 Plugin 和 Biz 依賴,完成隔離載入並按優先順序依次啟動。
  • Ark Plugin: SOFAArk 定義的特定目錄格式的 Fat Jar,使用 Maven 外掛 sofa-ark-plugin-maven-plugin 可以將多個二方包打包成一個 Plugin 對外外掛化輸出。Plugin 會包含一份配置檔案,通常包括外掛類匯入匯出配置、資源匯入匯出配置、外掛啟動優先順序等;執行時,SOFAArk 容器會使用獨立的 PluginClassLoader 載入外掛,並根據外掛配置構建類載入索引表、資源載入索引表。外掛和外掛之間、外掛和應用之間相互隔離。
  • Ark Biz: SOFAArk 定義的特定目錄格式的 Fat Jar,使用 Maven 外掛 sofa-ark-maven-plugin 可以將應用打包成 Biz 包。Biz 是工程應用以及其依賴包的組織單元,包含應用啟動所需的所有依賴和配置。一個 Ark 包中可以包含多個 Biz 包,按優先順序依次啟動,Biz 之間通過 SOFA JVM 服務 互動。

啟動 Ark 包,Ark Container 優先啟動,容器執行時自動解析 Ark 包中包含 Plugin 和 Biz,並讀取他們的配置資訊,構建類和資源的載入索引表;然後使用獨立的 ClassLoader 載入並按優先順序配置依次啟動。需要指出的是,Plugin 優先 Biz 被載入啟動。

SOFAArk 內部的類載入模型相對比較簡單,Plugin 之間是雙向類索引關係,即可以相互委託對方載入所需的類和資源;Plugin 和 Biz 是單向類索引關係,即只允許 Biz 索引 Plugin 載入的類和資源,反之則不允許。

總結

SOFAArk 定義了一套相對簡單的類載入模型,並結合特殊的打包格式、統一的程式設計介面、易擴充套件的外掛機制,從而提供了一套較為規範化的外掛化、模組化的開發方案。更多內容可以參考官方文件

文中涉及的相關連結

與 SOFA 相遇

3 月 24 日(本週日下午),SOFA Meetup#1-服務註冊中心、分散式事務重磅釋出 將在北京舉行。

席位有限,點選連結即可報名:tech.antfin.com/activities/…

倒數計時 3 天!期待與大家見面~

主海報-終.jpg

公眾號:金融級分散式架構(Antfin_SOFA)



相關文章