歡迎光臨
每天分享高質量文章

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

SOFAStack  

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

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

GitHub 地址:
https://github.com/alipay/sofa-ark

 

簡介

在大型軟體開發過程中,通常會推薦底層功能插件化、業務功能模塊化的開發樣式,以其達到低耦合、高內聚、功能復用的優點。基於此,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 容器之上合併部署,並通過統一的編程界面交互,如下:

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

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

靜態合併部署

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

動態合併部署

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

無論是靜態抑或動態合併部署都有存在宿主應用 (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 解決該依賴衝突問題:只需要把 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; 運行時邏輯結構圖如下:

在介紹這三個概念之前,先介紹 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 包工程目錄:

可以很直觀的看到 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 JVM 服務:

    https://www.sofastack.tech/sofa-boot/docs/sofa-ark-ark-jvm

  • SOFAArk 官方文件:

    https://www.sofastack.tech/sofa-boot/docs/sofa-ark-readme

赞(0)

分享創造快樂