做者:卫恒(宋国磊),SOFATracer 以及 SOFADashboard 开源负责人。java
本文根据 5月26日 SOFA Meetup#2上海站 《使用 SOFAStack 快速构建微服务》主题分享整理,着重分享如何使用 SOFADashboard 来管控 SOFAArk ,对于 SOFAArk 中的一些基础概念和知识不过多涉及;建议你们在阅读以前,先了解下 SOFAArk 的相关基本知识。git
现场回顾视频以及 PPT 见文末连接。github
SOFAArk 是一款基于 Java 实现的轻量级类隔离容器,主要提供类隔离和应用(模块)合并部署能力,由蚂蚁金服开源贡献。SOFAArk 在 0.6.0 版本 提供了很是丰富的功能特性,其中最核心的当属多应用(模块)合并部署这个能力。SOFAArk 自己提供了多种方式来支持多应用(模块)合并部署 ,包括基于命令行的管控,基于 API 的管控等。本篇将结合 SOFA 开源的管控端组件 SOFADashboard,来实现 SOFAArk 提供的合并部署和动态模块推送的功能。web
案例工程地址:https://github.com/sofastack-guides/sofa-dashbaord-samples-parentspring
复杂项目一般须要跨团队协做开发,各自负责不一样的组件,而众所周知,协调跨团队合做开发会遇到很多问题;好比各自技术栈不统一致使的依赖冲突,又好比往同一个 Git 仓库提交代码经常致使 merge 冲突。所以,若是能让每一个团队将负责的功能组件当成一个个单独的应用开发,运行时合并部署,经过统一的编程界面交互,那么将极大的提高开发效率及应用可扩展性。SOFAArk 提出了一种特殊的包结构 -- Ark Biz,用户可使用 Maven 插件将应用打包成 Biz,容许多 Biz 在 SOFAArk 容器之上合并部署,并经过统一的编程界面交互。sql
本篇所演示案例是上图的一个简化版,从总体上能够体现 SOFAArk多应用合并部署的能力。主要包括已经几个工程:编程
sofa-dashboard-ark-hostapp 和 sofa-dashboard-ark-provider 均做为 SOFAArk 中的 ark-biz 存在;sofa-dashboard-ark-hostapp 做为宿主应用对外提供服务。 bootstrap
上图的模型中,在宿主应用不重启的状况下,实现 provider 模块的动态替换,从而实现版本升级。springboot
在宿主应用启动时,provider 1.0.0 以静态合并部署方式“寄宿”到宿主应用中,这部分实际上与 SOFADashboard 管控是没有什么关系的,为了案例效果,在下面的案例中,关于静态合并部署的操做也会涉及到。服务器
最终的工程结构图以下:
本文须要启动 SOFADashboard 服务端,具体请参考 : Quick Start ;其余基础设施环境如 Zookeeper 、Mysql 等需提早准备。
本篇将经过 step by step 的方式来构建整个工程,为你们在实际的应用过程当中提供一种简单的思路,同时也帮助你们更好的理解 SOFAArk 中的一些点。
基础 API 提供模块,不须要依赖任何其余二方或者三方 JAR,这里仅提供一个接口。
public interface SofaJvmService { String test(); }
这个模块是 JVM 服务的提供方,也是后面须要在宿主应用中进行替换演示的模块包,这个模块自己也是一个 Web 应用。这里就来一步步分解下,如何将一个普通的 SpringBoot 工程改形成一个 ark-biz 工程。
新建 SpringBoot 工程推荐的方式有两种,一种是在 https://start.spring.io/ 进行下载,另一种是基于 IDEA 的 Spring 插件来生成;此处不在过多描述过程。
@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
根据官方文档,可使用 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>
从前面背景介绍中的设计理念图中能够看出,动态合并部署须要依赖的插件核心有两个,一个是 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>
执行 mvn clean package ,以后会在当前模块的 target 目录下生成 xxx-ark-biz.jar 的包。
前面已经构建好了所须要的一些基础工程,sofa-dashboard-ark-host 做为宿主应用,指望其具有的能力有如下几个:
基于以上几点功能,下面来分步骤实现。
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(); } }
这部分能够先参考阅读 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>
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=*
SOFAArk 提供了 config-ark-plugin 对接 Zookeeper 配置中心,用于运行时接受配置,达到控制 Biz 生命周期,引入以下依赖:
<!-- 引用ark 配置推送扩展插件--> <dependency> <groupId>com.alipay.sofa</groupId> <artifactId>config-ark-plugin</artifactId> </dependency>
参考 SOFAArk 配置,在 SOFAArk 配置文件 conf/ark/bootstrap.properties 增长以下配置:
com.alipay.sofa.ark.config.address=zookeeper://localhost:2181
基于上述全部的配置,将 host-app 打包,而后运行。
下面能够经过 SOFAArk 提供的 endpoint 来查看下当前应用的 biz state 信息:
这里只有宿主应用自身的 ark biz 状态信息,实际上咱们使用了静态合并部署。可是貌似 ark-biz 合并部署的包插件没有在 bizState 中体现出来。访问下 http://localhost:8085/test 咱们的 check rest 服务:
提示出来没有可用的 JVM 服务。
这里有个点是并不会去激活里面的 ark biz 包,须要经过经过 终端或者 API 的方式来进行激活,实际上只是激活了宿主应用自己的 ark-biz。
SOFADashboard 进行推送的原理能够参考前面背景介绍中的描述。下面主要来介绍如何使用 SOFADashboard 进行动态模块切换。
将 sofa-dashboard-ark-provider 这个 ark-biz 插件注册到 SOFADashboard:
填写插件的基本信息:
注册成功以后,模块列表以下:
点击添加版本,弹出新增版本表单,输入版本信息及当前版本对应的 ark biz 包文件地址;支持从文件服务器(http 协议)上拉取,也支持从本地文件(File 协议)系统获取。下面为了方便,使用从文件系统中获取,配置以下:
添加成功以后,插件列表以下:
点击插件列表后面的 关联应用案例,将插件与应用进行关联,以下:
点击插件列表后面的详情按钮,能够查看当前插件下全部应用信息和应用实例信息。
SOFADashboard 提供两种维度的命令推送:
下面演示基于 IP 维度的推送:
点击安装,安装过程当中,插件状态会发生变化, RESOLVED 状态为正在解析。
延迟 1~3s 以后,状态变为 ACTIVATED 状态:
再次访问下 http://localhost:8085/test 咱们的 check rest 服务:
实现了在不重启宿主应用的状况下,实现了内部业务逻辑的变动。
模块版本 1 运行一段时间以后,出现新的需求,但愿更改下模块版本 1 中的一些逻辑。在未使用动态模块的状况下,通常就须要新拉一个迭代,而后将原有的逻辑修改,而后发布上线。多是一个很是小的功能点,可是却须要走复杂的发布流程。
这个就能够借助动态模块的方式来实现版本的动态切换。修改 sofa-dashboard-ark-provider 模块逻辑实现,升级版本,从新打包 sofa-dashboard-ark-provider 。
在 SOFADashboard ,新增 2.0.0 版本,而且配置指定的版本 ark-biz 包的文件地址。添加成功以后以下:
进入详情界面,切换版本到 2.0.0:
执行安装,此时版本 2.0.0 状态将会变为非激活状态:
执行点击激活按钮进行激活,延迟 1~3s 以后,状态变动为激活状态:
再次访问下 http://localhost:8085/test 咱们的 check rest 服务:
能够看到,版本 2.0.0 中的逻辑已经生效了;切回到 1.0.0 ,此时 1.0.0 的状态变成了非激活状态:
本文分享了基于 SOFAArk 和 SOFADashboard 实现动态模块管控的能力。动态模块在实际业务中有很是丰富的场景,对主应用不发版,不重启的状况下实现具体模块的功能变动;在此基础上也能够实现版本灰度的能力。
本案例中,provider 也是一个独立的应用,其做为一个子模块在宿主应用 hostapp 中启动,所以也能够基于 SOFABoot 这种能力来实现多 Web 应用的合并部署的能力。
以上就是本次分享的所有内容。
现场回顾视频以及 PPT 地址:http://t.cn/AiKlmCmE