作者:衛恒(宋國磊),SOFATracer 以及 SOFADashboard 開源負責人。
本文根據 5月26日 SOFA Meetup#2上海站 《使用 SOFAStack 快速建構微服務》主題分享整理,着重分享如何使用 SOFADashboard 來管控 SOFAArk ,對于 SOFAArk 中的一些基礎概念和知識不過多涉及;建議大家在閱讀之前,先了解下 SOFAArk 的相關基本知識。
現場回顧視訊以及 PPT 見文末連結。

前言
SOFAArk是一款基于 Java 實作的輕量級類隔離容器,主要提供類隔離和應用(子產品)合并部署能力,由螞蟻金服開源貢獻。
在
0.6.0 版本提供了非常豐富的功能特性,其中最核心的當屬多應用(子產品)合并部署這個能力。
本身提供了多種方式來支援多應用(子產品)合并部署 ,包括基于指令行的管控,基于 API 的管控等。本篇将結合 SOFA 開源的管控端元件
SOFADashboard,來實作
提供的合并部署和動态子產品推送的功能。
案例工程位址:
https://github.com/sofastack-guides/sofa-dashbaord-samples-parent背景
複雜項目通常需要跨團隊協作開發,各自負責不同的元件,而衆所周知,協調跨團隊合作開發會遇到不少問題;比如各自技術棧不統一導緻的依賴沖突,又比如往同一個 Git 倉庫送出代碼常常導緻 merge 沖突。是以,如果能讓每個團隊将負責的功能元件當成一個個單獨的應用開發,運作時合并部署,通過統一的程式設計界面互動,那麼将極大的提升開發效率及應用可擴充性。SOFAArk 提出了一種特殊的包結構 -- Ark Biz,使用者可以使用 Maven 插件将應用打包成 Biz,允許多 Biz 在 SOFAArk 容器之上合并部署,并通過統一的程式設計界面互動。
案例模型
本篇所示範案例是上圖的一個簡化版,從整體上可以展現 SOFAArk多應用合并部署的能力。主要包括已經幾個工程:
- sofa-dashboard-ark-hostapp : 宿主應用
- sofa-dashboard-ark-facade : 提供接口 API
- sofa-dashboard-ark-provider :提供接口 API 的具體實作,将釋出一個 JVM 服務
sofa-dashboard-ark-hostapp 和 sofa-dashboard-ark-provider 均作為 SOFAArk 中的 ark-biz 存在;sofa-dashboard-ark-hostapp 作為宿主應用對外提供服務。
上圖的模型中,在宿主應用不重新開機的情況下,實作 provider 子產品的動态替換,進而實作版本更新。
在宿主應用啟動時,provider 1.0.0 以靜态合并部署方式“寄宿”到宿主應用中,這部分實際上與 SOFADashboard 管控是沒有什麼關系的,為了案例效果,在下面的案例中,關于靜态合并部署的操作也會涉及到。
最終的工程結構圖如下:
環境準備
本文需要啟動 SOFADashboard 服務端,具體請參考 :
Quick Start;其他基礎設施環境如 Zookeeper 、Mysql 等需提前準備。
工程建構
本篇将通過 step by step 的方式來建構整個工程,為大家在實際的應用過程中提供一種簡單的思路,同時也幫助大家更好的了解 SOFAArk 中的一些點。
sofa-dashboard-ark-facade
基礎 API 提供子產品,不需要依賴任何其他二方或者三方 JAR,這裡僅提供一個接口。
public interface SofaJvmService {
String test();
}
sofa-dashboard-ark-provider
這個子產品是 JVM 服務的提供方,也是後面需要在宿主應用中進行替換示範的子產品包,這個子產品本身也是一個 Web 應用。這裡就來一步步分解下,如何将一個普通的 SpringBoot 工程改造成一個 ark-biz 工程。
1、建立一個 SpringBoot 工程
建立 SpringBoot 工程推薦的方式有兩種,一種是在
https://start.spring.io/進行下載下傳,另外一種是基于 IDEA 的 Spring 插件來生成;此處不在過多描述過程。
2、工程基本能力實作
- 引入 sofa-dashboard-ark-facade 依賴,先将需要提供的 JVM 服務實作:
@SofaService
@Service
public class SofaJvmServiceImpl implements SofaJvmService {
@Override
public String test() {
return "first version biz";
}
}
NOTE: SofaService 的作用是将一個 Bean 釋出成一個 JVM 服務, 是以這裡需要加上 Spring 提供的 @Service 注解将 SofaJvmServiceImpl 标注為一個 Bean。
- 配置檔案:
spring.application.name=biz-ark-test
server.port=8800
logging.path=./logs
3、配置打包插件,将應用打包成 ark-biz
根據官方文檔,可以使用 sofa-ark-maven-plugin 插件将一個普通的工程打包成一個 ark biz 包。這裡直接給出本篇中工程的配置:
<plugin>
<groupId>com.alipay.sofa</groupId>
<artifactId>sofa-ark-maven-plugin</artifactId>
<version>0.6.0</version>
<executions>
<execution>
<!--goal executed to generate executable-ark-jar -->
<goals>
<goal>repackage</goal>
</goals>
<!--ark-biz 包的打包配置 -->
<configuration>
<!--是否打包、安裝和釋出 ark biz,詳細參考 Ark Biz 文檔,預設為false-->
<attach>true</attach>
<!--ark 包和 ark biz 的打包存放目錄,預設為工程 build 目錄-->
<outputDirectory>target</outputDirectory>
<!--default none-->
<arkClassifier>executable-ark</arkClassifier>
<!-- ark-biz 包的啟動優先級,值越小,優先級越高-->
<priority>200</priority>
<!--設定應用的根目錄,用于讀取 ${base.dir}/conf/ark/bootstrap.application 配置檔案,預設為 ${project.basedir}-->
<baseDir>../</baseDir>
</configuration>
</execution>
</executions>
</plugin>
4、工程依賴
從前面背景介紹中的設計理念圖中可以看出,動态合并部署需要依賴的插件核心有兩個,一個是 runtime plugin,一個是 config plugin(沒有涉及到 RPC 服務相關);由于 provider 并不是作為宿主應用,其本身不需要具備動态配置的能力,是以這裡僅需要引入 runtime plugin 來為目前 ark-biz 工程提供運作時環境即可。
<!-- runtime plugin -->
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>runtime-sofa-boot-plugin</artifactId>
</dependency>
<!-- 其他依賴 -->
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>healthcheck-sofa-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.glmapper.bridge.boot</groupId>
<artifactId>sofa-dashboard-ark-facade</artifactId>
</dependency>
5、編譯打包
執行 mvn clean package ,之後會在目前子產品的 target 目錄下生成 xxx-ark-biz.jar 的包。
sofa-dashboard-ark-host
前面已經建構好了所需要的一些基礎工程,sofa-dashboard-ark-host 作為宿主應用,期望其具備的能力有以下幾個:
- 提供可以直覺的 check 子產品變更後的結果
- 提供能夠給 provider 1.0.0 版本 ark-biz 包運作的宿主環境
- 能夠通過 SOFAArk 提供的狀态 endpoint 檢視插件狀态
- 能夠支援 Zookeeper 下發指令,控制 Biz 的生命周期
基于以上幾點功能,下面來分步驟實作。
1、提供一個簡單的 Rest 接口來 check 結果
sofa-dashboard-ark-host 本身也是一個 Web 應用,是以在這個提供一個 Rest 接口,具體實作是通過@SofaReference 調用 provider ark-biz 包中釋出的 JVM 服務。
@RestController
public class TestController {
@SofaReference
SofaJvmService sofaJvmService;
@RequestMapping("test")
public String test(){
return sofaJvmService.test();
}
}
2、作為宿主應用
- ARK 容器配置
這部分可以先參考閱讀
SOFAArk 配置。本案例中簡單配置了一份 ARK 容器的配置檔案。
# log 日志目錄
logging.path=./logs
# 指定zookeeper 服務位址
com.alipay.sofa.ark.config.address=zookeeper://localhost:2181
# 指定宿主應用名
com.alipay.sofa.ark.master.biz=host-app
com.alipay.sofa.ark.master.biz 預設情況下是宿主應用的 artifactId。如果這裡指定了名字,則在宿主應用的插件配置裡面需要使用此名字。
- 依賴引入
引入 sofa-ark-springboot-starter 、web-ark-plugin 以及 provider ark biz 包。
<!-- 引用ark starter-->
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>sofa-ark-springboot-starter</artifactId>
</dependency>
<!-- 引用ark web插件-->
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>web-ark-plugin</artifactId>
</dependency>
<!-- 引入 sofa-dashboard-ark-provider ark-biz ,這裡屬于靜态合并部署情況-->
<dependency>
<groupId>com.glmapper.bridge.boot</groupId>
<artifactId>sofa-dashboard-ark-provider</artifactId>
<version>1.0.0</version>
<classifier>ark-biz</classifier>
</dependency>
- 插件配置
<plugin>
<groupId>com.alipay.sofa</groupId>
<artifactId>sofa-ark-maven-plugin</artifactId>
<version>0.6.0</version>
<executions>
<execution>
<id>default-cli</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<!--指定優先級-->
<priority>100</priority>
<!--指定baseDir-->
<baseDir>../</baseDir>
<!--bizName,這裡需要和 bootstrap 中指定的master.biz 配置保持一緻,預設為 artifactId-->
<bizName>host-app</bizName>
</configuration>
</plugin>
3、狀态檢視
SOFAArk 提供了 /bizState 這樣一個 endpoint 用來擷取目前插件的版本及狀态資訊。這裡就在宿主應用中引入actuator 依賴并進行相關配置。
<!-- 引用 actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
application.properties 中配置暴露所有端點。
management.endpoints.web.exposure.include=*
4、提供動态配置插件能力
SOFAArk 提供了 config-ark-plugin 對接 Zookeeper 配置中心,用于運作時接受配置,達到控制 Biz 生命周期,引入如下依賴:
<!-- 引用ark 配置推送擴充插件-->
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>config-ark-plugin</artifactId>
</dependency>
參考
,在 SOFAArk 配置檔案 conf/ark/bootstrap.properties 增加如下配置:
com.alipay.sofa.ark.config.address=zookeeper://localhost:2181
靜态合并部署示範
基于上述所有的配置,将 host-app 打包,然後運作。
- mvn clean install
- java -jar sofa-dashboard-ark-hostapp-1.0.0.jar
下面可以通過 SOFAArk 提供的 endpoint 來檢視下目前應用的 biz state 資訊:
這裡隻有宿主應用自身的 ark biz 狀态資訊,實際上我們使用了靜态合并部署。但是貌似 ark-biz 合并部署的包插件沒有在 bizState 中展現出來。通路下
http://localhost:8085/test我們的 check rest 服務:
提示出來沒有可用的 JVM 服務。
這裡有個點是并不會去激活裡面的 ark biz 包,需要通過通過 終端或者 API 的方式來進行激活,實際上隻是激活了宿主應用本身的 ark-biz。
通過 SOFADashboard 進行動态推送
SOFADashboard 進行推送的原理可以參考前面背景介紹中的描述。下面主要來介紹如何使用 SOFADashboard 進行動态子產品切換。
注冊插件
将 sofa-dashboard-ark-provider 這個 ark-biz 插件注冊到 SOFADashboard:
填寫插件的基本資訊:
注冊成功之後,子產品清單如下:
增加版本
點選添加版本,彈出新增版本表單,輸入版本資訊及目前版本對應的 ark biz 封包件位址;支援從檔案伺服器(http 協定)上拉取,也支援從本地檔案(File 協定)系統擷取。下面為了友善,使用從檔案系統中擷取,配置如下:
添加成功之後,插件清單如下:
關聯應用
點選插件清單後面的 關聯應用案例,将插件與應用進行關聯,如下:
詳情檢視
點選插件清單後面的詳情按鈕,可以檢視目前插件下所有應用資訊和應用執行個體資訊。
指令推送
SOFADashboard 提供兩種次元的指令推送:
- 基于應用次元,目前應用所有的執行個體都會監聽到此指令變更;
- 基于 IP 次元,分組次元的單 IP 場景。
下面示範基于 IP 次元的推送:
1、安裝
點選安裝,安裝過程中,插件狀态會發生變化, RESOLVED 狀态為正在解析。
延遲 1~3s 之後,狀态變為 ACTIVATED 狀态:
再次通路下
我們的 check rest 服務:
實作了在不重新開機宿主應用的情況下,實作了内部業務邏輯的變更。
2、版本切換
子產品版本 1 運作一段時間之後,出現新的需求,希望更改下子產品版本 1 中的一些邏輯。在未使用動态子產品的情況下,一般就需要新拉一個疊代,然後将原有的邏輯修改,然後釋出上線。可能是一個非常小的功能點,但是卻需要走複雜的釋出流程。
這個就可以借助動态子產品的方式來實作版本的動态切換。修改 sofa-dashboard-ark-provider 子產品邏輯實作,更新版本,重新打包 sofa-dashboard-ark-provider 。
在 SOFADashboard ,新增 2.0.0 版本,并且配置指定的版本 ark-biz 包的檔案位址。添加成功之後如下:
進入詳情界面,切換版本到 2.0.0:
執行安裝,此時版本 2.0.0 狀态将會變為非激活狀态:
執行點選激活按鈕進行激活,延遲 1~3s 之後,狀态變更為激活狀态:
可以看到,版本 2.0.0 中的邏輯已經生效了;切回到 1.0.0 ,此時 1.0.0 的狀态變成了非激活狀态:
小結
本文分享了基于 SOFAArk 和 SOFADashboard 實作動态子產品管控的能力。動态子產品在實際業務中有非常豐富的場景,對主應用不發版,不重新開機的情況下實作具體子產品的功能變更;在此基礎上也可以實作版本灰階的能力。
本案例中,provider 也是一個獨立的應用,其作為一個子子產品在宿主應用 hostapp 中啟動,是以也可以基于 SOFABoot 這種能力來實作多 Web 應用的合并部署的能力。
以上就是本次分享的全部内容。
SOFA Meetup 上海站回顧資料
現場回顧視訊以及 PPT 位址:
http://t.cn/AiKlmCmE