開源 | SOFABoot 類隔離原理剖析

開源 | SOFABoot 類隔離原理剖析

來自專欄 sofastack

原創聲明:本文系作者原創,謝絕個人、媒體、公眾號或網站未經授權轉載,違者追究其法律責任。

SOFABoot 是螞蟻金服中間件團隊開源的基於 Spring Boot 的一個開發框架,其在 Spring Boot 基礎能力之上,增加了類隔離能力,以更好地解決隨著工程應用變得臃腫龐大後帶來的包衝突問題。類隔離能力天生帶來模塊化能力,同樣給協作開發帶來便利。

SOFABoot 的類隔離能力藉助單獨的組件 SOFAArk 實現,遵循 Spring Boot 依賴即服務的思想,只要工程中引入了 SOFAArk 組件依賴,類隔離能力即生效。

在上一篇文章 《在 Spring Boot 中集成 SOFABoot 類隔離能力》中,我們詳細介紹了 SOFABoot 類隔離能力的使用背景及其使用方式。本文將介紹 SOFABoot 類隔離組件 SOFAArk 的實現原理。

理解 SOFAArk 三要素

SOFAArk 類隔離框架定義了三個概念,Ark Container,Ark Plugin,Ark Biz。

在介紹這三個主角之前,我們先來介紹另一個管家:Ark 包。我們都知道一個標準的 Spring Boot 應用可以藉助 Spring 官方提供的打包插件:

<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId></plugin>

將應用打包成一個可執行 FatJar。相對應的,Ark 包則是 SOFABoot 官方提供的打包插件:

<plugin> <groupId>com.alipay.sofa</groupId> <artifactId>sofa-ark-maven-plugin</artifactId></plugin>

將應用打包成一個具有類隔離能力的可執行 FatJar,稱之為 Ark 包。下圖是粗略地對比兩者的目錄結構差別:

可以看到 Ark 包作為應用部署包的分發格式,它包含有 Ark Container,Ark Plugin 和 Ark Biz 三種格式模塊。這裡我們不對 Ark 包或者其他格式模塊的目錄結構作分析,感興趣的同學可以點開文末附上的相關鏈接。我們重點介紹這三個角色的功能。

  • Ark Container: Ark 容器,是組件 SOFAArk 的核心,運行 Ark 包時,Ark 容器會最先啟動,負責應用運行時的管理,主要包括構建 Ark Plugin 和 Ark Biz 的類導入導出關係表、啟動並初始化 Ark Plugin 和 Ark Biz、管理 Ark Plugin 服務的發布和引用等等。
  • Ark Plugin: SOFAArk 定義的一種模塊格式,由若干個 Jar 包組成的一個 FatJar,開發人員可以藉助官方提供的 maven 打包插件將若干 Jar 包打包成一個 Ark Plugin 供應用依賴。運行時,由獨立的類載入器載入,因此有隔離需求的 Jar 包建議打包成 Ark Plugin 供應用依賴。
  • Ark Biz: SOFAArk 定義的一種模塊格式,是應用及其依賴的所有三方包組成的一個 FatJar,需要注意的是,Ark Biz 不會包含應用依賴的 Ark Plugin。運行時,Ark Biz由獨立的類載入器載入,藉助類導入導出關係表,Ark Biz 可以使用 Ark Plugin 的導出類和資源。

SOFAArk 運行時隔離

根據上一節的描述可以知道 SOFABoot 類隔離關鍵是理解 SOFAArk 定義的三個概念,Ark Container,Ark Plugin 和 Ark Biz。下圖表示的是應用啟動後,運行時 Ark Container,Ark Plugin,Ark Biz 的邏輯分層圖:

我們將先以 Ark Plugin 入手來介紹 SOFABoot 類隔離的實現原理。

Ark Plugin 隔離

開發者藉助 SOFABoot 官方提供的插件:

<plugin> <groupId>com.alipay.sofa</groupId> <artifactId>sofa-ark-plugin-maven-plugin</artifactId></plugin>

可以將 Java 模塊打包成一個 Ark Plugin,這裡我們不討論該打包插件的配置參數和使用方式,感興趣的同學可以點開文末附上的相關鏈接以及學習 SOFABoot 類隔離能力使用篇。只需要知道,Ark Plugin 主要包含元信息有:插件啟動器、導出類、導入類、導出資源、導入資源、優先順序等,這些元信息保存在 Ark Plugin 中的 META-INF/MANIFEST.MF 中,一份典型的 MANIFEST.MF 文件樣式如下:

Manifest-Version: 1.0groupId: com.alipay.sofaartifactId: sample-ark-pluginversion: 0.3.0-SNAPSHOTpriority: 1000pluginName: sample-ark-pluginactivator: com.alipay.sofa.ark.sample.activator.SamplePluginActivatorimport-packages: import-classes: import-resources: export-packages: com.alipay.sofa.ark.sample.common.*,com.alipay.sofa.ark.sampleexport-classes: com.alipay.sofa.ark.sample.facade.SamplePluginServiceexport-resources: Sample_Resource_Exported

在上面我們提到,運行 Ark 包時,類隔離容器 Ark Container 會最先啟動,然後 Ark Container 會接管整個應用的啟動過程。針對 Ark Plugin 處理邏輯如下:

  • 首先解析 Ark 包中引入的所有 Ark Plugin,讀取插件元信息,構建類/資源導入導出關係索引表。
  • 提前生成所有插件類載入器,每個 Ark Plugin 都使用獨立的類載入器,管理插件類載入邏輯,藉助第一步生成的類導入導出關係表,突破 Java 原生的雙親委派模型,可以委託其他插件載入所需類,構建一個類 OSGi 的網狀類載入模型。
  • 根據插件優先順序,依次調用插件啟動器。在插件啟動器中,插件開發者可以向容器註冊服務以方便其他插件引用,也可以引用其他插件發布的服務,及插件啟動所需的初始化操作。

需要明確一點,為了讓類載入模型足夠簡單,Ark 容器在啟動任何插件前,會把所有的插件類載入器提前構建完畢。Ark Plugin 可以相互委託載入,插件優先順序只是影響插件的啟動順序,而且也不強制要求每個 Ark Plugin 都要有啟動器。

啟動完所有插件後,Ark Container 則開始負責啟動 Ark Biz 模塊。

Ark Biz 隔離

Ark Container 在完成 Ark Plugin 的隔離和啟動後,則開始準備 Ark Biz 的隔離和啟動。

在上文中提到,應用打成 Ark 包後,Ark 包會包含 Ark Plugin 模塊和 Ark Biz 模塊。實際上 Ark Biz 其實就是應用及其所有的三方依賴打成的 FatJar 包,Ark Biz 不會包含應用引入的 Ark Plugin。開發者藉助 SOFABoot 官方提供的插件:

<plugin> <groupId>com.alipay.sofa</groupId> <artifactId>sofa-ark-maven-plugin</artifactId></plugin>

可以將 Java(Spring Boot) 應用打包成一個 Ark Biz,這裡我們不討論該打包插件的配置參數和使用方式,感興趣的同學可以點開文末附上的相關鏈接以及學習 SOFABoot 類隔離能力使用篇。只需要知道,Ark Biz 主要包含元信息有:應用啟動入口、禁止導入類、禁止導入資源等。這些元信息保存在 Ark Biz 中的 META-INF/MANIFEST.MF 中,一份典型的 MANIFEST.MF 文件樣式如下:

Manifest-Version: 1.0Archiver-Version: Plexus ArchiverCreated-By: Apache Maven 3.2.5Build-Jdk: 1.8.0_101Built-By: qilong.zqlArk-Biz-Name: sofa-ark-sample-springboot-arkdeny-import-resources:deny-import-packages:deny-import-classes:Main-Class: com.alipay.sofa.ark.sample.springbootdemo.SpringbootDemoApplication

Ark Biz 和 Ark Plugin 有很大的不同,最明顯的則是 Ark Biz 單向依賴 Ark Plugin,即 Ark Biz 只能單向委託 Ark Plugin 載入類和資源,反之則不可以。實際上在運行時,Ark Biz 是運行在 Ark Plugin 之上,Ark Container也是先啟動所有 Ark Plugin 然後啟動 Ark Biz。默認情況下,Ark Plugin 導出的所有類和資源都能被 Ark Biz 委託載入到,為了方便應用開發者能夠自主控制類載入邏輯,允許在打包插件中配置禁止導入類和禁止導入資源,如此,對於配置的類和資源, Ark Biz 能夠優先載入內部包含的類,而不會委託給 Ark Plugin 載入。Ark Container 針對 Ark Biz 處理邏輯如下:

  • 首先解析 Ark 包中 Ark Biz 模塊,讀取元信息,構建類/資源導入導出關係索引表。
  • 生成 Ark Biz 類載入器,管理 Ark Biz 類載入邏輯,藉助第一步生成的類導入導出關係表,突破 Java 原生的雙親委派模型,可以委託 Ark Plugin 載入所需類和資源。
  • 調用應用啟動入口,啟動應用。

如此,Ark 包即完成整個啟動過程。

和 OSGi 對比

作為開源界早負盛名的動態模塊系統,基於 OSGi 規範的 Equinox、Felix 等同樣具備類隔離能力,然而他們更多強調的是一種編程模型,面向模塊化開發,有一整套模塊生命周期的管理,定義模塊通信機制以及複雜的類載入模型。作為專註於解決依賴衝突的隔離框架,SOFAArk 專註於類隔離,簡化了類載入模型,因此顯得更加輕量。

其次在 OSGi 規範中,所有的模塊定義成 Bundle 形式,作為應用開發者,他需要了解 OSGi 背後的工作原理,對開發者要求比較高。在 SOFAArk 中,定義了兩層模塊類型,Ark Plugin 和 Ark Biz,應用開發者只需要添加隔離的 Ark Plugin 依賴,對本身的開發沒有任何影響,基本沒有開發門檻。

正在做的事

全文讀下來,你可能會產生這樣的一個疑惑:如果在應用中引入其他應用打包的 Ark Biz 會如何呢?

目前 SOFAArk 是可以啟動多個 Ark Biz 的,比較遺憾的是,現在 Ark Biz 之間沒法做到服務通信。如果你之前讀完過上一篇 SOFABoot 類隔離使用篇及這篇原理篇,你也許會發現,雖然 SOFAArk 是一個純粹的類隔離框架,但是基於 SOFAArk 之上,可以開發各具功能特色的 Ark Plugin,補充框架能力,供應用開發者按需依賴使用,比如已經推出的 SOFARPC Ark Plugin。回到上面的問題,為了解決多個 Ark Biz 合併部署的問題,我們正在開發一個新的 Ark Plugin,Jarslink2.0。

在螞蟻內部,多個應用合併部署在同一個 JVM 之上,是一件常見的事情。這樣帶來的主要優勢如下:

  • 無關應用合併部署:有些應用在獨立部署時,相互之間沒有服務依賴,而且這些應用承擔業務體量都偏小,單獨佔有一台物理機部署比較浪費資源。這些應用合併部署,能夠節省成本。
  • 相關應用合併部署:多個應用之間存在服務依賴,獨立部署時,各應用之間使用 RPC 調用,雖然使用了分散式架構,穩定性高,但依然存在網路抖動導致的延時性問題。這些應用合併部署,RPC 調用轉為JVM內部調用,縮減調用開銷。

當然,作為螞蟻內部非常重要的一項技術創新,合併部署在特定的業務背景下有著更為重要的意義,也遠不止上面提到的兩點優勢,比如故障的隔離等等。

說回到 Jarslink2.0,這個 SOFABoot 官方開發的 Ark Plugin,主要是為了解決多個 Ark Biz 運行時管理問題。我們知道,每個 Java(Spring Boot) 應用,都可以通過我們的 maven 插件打包成 Ark Biz 供其他應用依賴。目前 SOFAArk 框架只能做到隔離 Ark Biz,作為框架能力的補充,Jarslink2.0 插件專門管理多個 Ark Biz 的運行時。這裡默認每個 Ark Biz 都是一個 SOAFBoot/Spring Boot 工程,Jarslink2.0 提供的能力如下:

  • 動態安裝、卸載 Ark Biz。
  • Ark Biz 之間使用註解和 xml 兩種形式發布和引用 jvm 服務,解決多 Ark Biz 服務依賴問題。
  • Ark Biz 如果使用了 SOFARPC 能力,可以自動完成 RPC 轉 JVM 內部調用。

在這裡特別感謝方騰飛, 螞蟻內部花名 @清英 ,也是我們熟知的並發編程網(ifeve.com/)創始人。清英在螞蟻內部開發的 Jarslink1.0 在網商銀行已經落地使用很長一段時間,Jarslink2.0 是在 Jarslink1.0 基礎之上,結合 SOFABoot 類隔離框架,提供了更加通用的應用(模塊)隔離和通信的實現方案,敬請期待!

歡迎微博關注@SOFAStack 與我們互動,相關傳送門:

  • Ark 包目錄結構及其打包插件的使用

    alipay.github.io/sofast
  • Ark Plugin 目錄結構及其打包插件的使用

    alipay.github.io/sofast
  • Ark Biz 目錄結構及其打包插件的使用

    alipay.github.io/sofast
  • Ark Plugin 的工程示例

    github.com/alipay/sofa-
  • Spring Boot github.com/alipay/sofa-

weixin.qq.com/r/YymEnET (二維碼自動識別)


推薦閱讀:

GitHub項目2018-06-01更新精選
熱點 | 四月最佳Github項目庫與最有趣Reddit熱點討論
Compare.NET Objects對象比較組件
來自角蜂鳥SDK開發者的第一篇閑談
科普一下GPL和開源軟體

TAG:開源 | 開源項目 | 開源軟體 |