jvm-sandbox生态简介
jvm-sandbox 是 “一种JVM的非侵入式运行期AOP解决方案”,来自于阿里开源。
先讲狭义的sandbox,它基于JVMTI
来实现jvm字节码替换,并基于此进行一层抽象,实现对任意方法,执行前、执行后、异常时添加使用方想要做的一些动作,因为sandbox对JVMTI做了良好的封装,所以只要按照sandbox的规范来写,添加的代码都是大家最熟悉的纯java代码。(比如官方的这个例子
)
在广义的讲sandbox生态,sandbox这个能力虽然大大降低了JVMTI
的使用门槛也提供了更高级的抽象,但如果止步于此就只能算是一个工具而已。而其作者思路不仅仅局限于此,基于这个能力发挥了想想空间,其内部开源了一些sandbox的module,又在某些细分的领域里做了更加高级的抽象,其中最具代表性的就是jvm-sandbox-repeater,而且这个生态已开源,所以我们也可以照猫画虎开发自己的module,实现更多的细分领域的模块开发。
就像作者说的:做一个底层中台,让每一位技术人员都可以在它的基础上快速的实现业务功能。
为什么要写这篇文章
最近对sandbox生态里开源的一些代码做了一些研读,也尝试做了一些落地,有一些心得、有一些想法,之前也写了一篇文章做了记录。
随着对sanbox生态体系了解的深入,更加意识到他目前并不是一个可以开箱即用的可落地方案,所以想把自己脑子里的一个整体的蓝图进行一个阐述:在公司内部自己团队中,如果要充分利用sandbox生态的能力,整体平台搭建的蓝图是什么样的,要做哪些工作,期望对大家一些帮助和灵感。
整体架构
我的设计,整体需要分四层,可以按照由下至上的进行落地,在数据层
和基础层搭建完成之后即具备基本可用能力,再向上的模块管理层和应用层更多的是实现拓展性以及流程化、规范化、自动化的能力。
数据层
数据层要基于大数据的各种技术,包括:存储、批处理、流处理、采集等,再向上输出数据采集、数据清洗、数据存储、数据查询能力。这块如果是小体量公司,也可以基于mysql数据库做小成本落地。当然这块一般有一定体量的公司大数据这一块都是必备的基础设施,此处不是本文重点,不在详细展开。
基础层
基础层这一块主要实现如下四个功能:
- sandbox版本管理
- sandbox 运行管理
- sandbox module管理
- sandbox module 运行管理
为什么要去实现这四个能力呢?为了实现更上层的场景,我们需要向不同的集群、不同服务、不同副本植入不同的module,不同的module又有不同的版本,版本更新可能还需要进行灰度,如果不具备对sandbox module的中心化管理能力,后面会比较麻烦。
另外,sandbox本身后续也会做版本升级,你肯定不想因为升级sandbox版本更新一遍线上所有服务吧?
这块实现起来有一些需要考虑的点和方案,会详细进行展开。
基础层整体架构
sandbox-ota-server
此处套用了物联网里的OTA的概念,ota-server是中心化的版本分发和管理平台,需要设计好与sandbox-ota-agent之间的协议,保留好拓展性。我的想法是只需要一个http接口,定时接受ota-agent的心跳请求,服务端这边可以从心跳请求中取得客户端基本信息以及sandbox、sandbox-module的checkSum信息;然后基于ota的策略,返回版本更新指令;然后ota-agent这边会根据返回的指令下载升级包,并进行升级动作。
心跳接口参考:
POST /ota/version?cluster=&app=&instanceId=&type=build/running
REQUEST BODY
{
"sandbox":"checkSum",
"module-x":"checkSum"
}
RESPONSE
{
"code": "",
"data": {
"sandbox":"http://xxxx",
"module-x":"http://xxxxx"
}
}
当然此处协议上有许多细节需要在详细设计阶段进行考虑,比如ota-agent这边对安装包的后续处理要做到通用、可拓展,不能后续比如有某些复杂的module开发出来,但不支持升级。此处设计思路上做简单提醒:
- sanbox可以按照固化模式进行升级
- sandbox-module建议支持zip包和jar包两种升级模式,zip包模式下可以实现升级配置文件,类似FOTA的场景
- 文件包的放置目录需要可灵活配置,比如zip包里是否可以放置一个properties文件,约定要文件放置规则
- ota心跳协议里query里有一个字段
type=build/running
这块先不要纠结,后面会做解释
sandbox-ota-agent
ota-agent这一边,我是基于目前最常见的k8s部署模式进行设计的。
在基于k8s进行部署时,jvm这边一定会有一个基础镜像,这个基础镜像原本就是提供了一些基础的jvm优化和配置,而此时我们要做的是开发一个ota-agent程序,并把程序植入到基础镜像中,在程序启动和构建时可以拉取对应的sandbox和sandbox-module版本。
程序逻辑上主要就是基于上面的协议,基于返回值对升级包进行升级处理,同事ota-agent也可以提供一些标准的http接口,比如sandbox本身的启动、停止等功能。
cluster-proxy
这个主要是用来解决跨集群网络不通所涉及的网络解决方案,可以是一个7层的网络代理服务器,在k8s集群里可以通过ingress来做,不过建议和业务的ingress做好隔离,并对sandbox接口做好鉴权。此处都是纯工具使用层面的事情,不展开。
既要考虑运行时的方便又要考虑不留后遗症
平台搭建起来后,我们会将各种各样的module安装到我们的业务副本上,如果只基于ATTACH模式进行安装,那么当服务重启、版本更新等情况发生时,我们ATTACH的动作都需要重新再做一遍;这样一方面会消耗服务器性能,另一方面会对module的生效时间造成一定的窗口期,对于某些敏感module,可能是不能容忍的。比如,我们开发了一个fastjson安全漏洞修复插件,每次都需要服务启动完成后20s后才能生效,那么就有可能会给攻击者以可乘之机。所以设计上需要对这个问题进行考虑。
我的建议是基础层支持ATTACH模式和AGENT模式并用,既可以在构建时植入module也可以在运行时植入module。具体的模块编排和协调由上一层的模块管理层实现,基础层只是在设计上保留两种能力。
构建时植入的实现
在源码变为镜像的过程中,会到ota-server拉取一次安装包(上文里http协议层query里的参数type的作用就和这个有关系)。服务启动后,就不再拉取已安装过的module了。这样可以通过agent模式实现jvm进程启动就具备必要的module,避免运行时通过attach模式安装造成的滞后、性能开销等问题。
固化module和临时module的概念
ota-server里对模块要有临时和固化的概念,只有固化的module才会在image build阶段装载到镜像里。至于一个module什么时候变为固化的module,要接受上一层模块管理层
和应用层
的控制。在不通的细分领域是不一样的。比如在安全漏洞修复领域,经过验证的漏洞修复module就需要变为固化module了;在线上诊断领域临时加的一些日志,就不需要固化。
另外,我们的固化module可以按照集群、app、甚至副本进行控制,比如有些module可以做到对某一个app进行固化。
模块管理层
基础层是一切的基础,有了这层之后,我们基本就可以具备简单的使用能力,只是使用方法上不那么平台化。
模块管理层,主要是在module层面进行个性化管理,封装抽象通用的模块级api供业务层使用。
同时这一层也是对下层的基础层管理控制台页面的实现层,可以通过页面对集群内各个服务sandbox版本和运行状态、sandbox module版本和运行状态、进行页面化管理。
同时也可以对一些基础层和数据层之间的管理配置放到这一层的页面上进行管理,比如数据采集规模查看、数据采集点管理、数据清洗进度等。
总之这一层可以做一些业务层之外的模块级通用的web页面,提供模块管理的窗口。
这一层技术层面设计空间不大,更多的是功能设计的考量,可以随着使用深度的加强,逐步迭代。
应用层
到了这一层,就是直接面向终端用户的一层了。这一层的某一个细分领域,可以对标到官方的 repeater-console](https://github.com/alibaba/jvm-sandbox-repeater/tree/master/repeater-console), 但是官方的repeater console太糙了,这一层我觉得每一个公司的使用场景不同,需要结合自己的场景进行考虑。
此处结合repeater场景,谈一下我的想法。
官方的repeater功能理解如下:
这个项目,只能说是给大家一个demo,抛砖引玉。
不谈技术层面,从功能设计上讲,这个demo其实是有一些概念缺失的。
下面我就说一下我的设计想法,此处更多的是功能&流程设计。
概念模型
核心概念至少要包含上图中的概念,每个服务可以提前配置很多功能点,每一个功能点可以有一份专属的配置,配置好入口的uri、入口执行函数、需要的子调用插件。
- 功能点可以有最懂功能的产品经理维护
- 功能点配置可以由最熟悉代码的开发人员维护
- 录制批次由测试人员维护
针对功能做好合理的规划和拆分,不同的功能由不同的团队使用,虽然这个是功能设计,但和我们技术设计里的康菲定律
真心是异曲同工。
试想,如果上面的功能一股脑全部给测试去做,这个功能平台只能说是技术上完美落地了,但使用层面落地情况肯定是差强人意的,总体落地效果会大打折扣。
概念模型搞清楚后,就可以梳理功能点清单,然后设计具体的功能点了,这里不再详细展开。
关于应用层,不同的细分领域,都有很多需要注意的地方;每一个领域,都可以单独拿出一篇文章来进行展开了。
结束语
sandbox开源生态,给我们提供了很大的想象空间,但如果真的想在公司内部落地,还有很多工作要做。
这部分工作的难点不仅仅只在技术层面、还有功能设计层面的挑战,需要一个技术和产品都过硬的团队去执行,否则还是很难落地的。
当然这个落地的过程,相信还是要付出很大的人力成本的,对一般的小公司来讲这种事情只能作为自驱的事项缓慢推进。
这是一篇从宏观设计调度的文章,目的是给大家一个思路,抛砖引玉。
文章内容和本人精力有限,很难一篇文章说出全部,在此也欢迎斧正和共同探讨。
下面是我写的其他文章,欢迎查阅:
异步编程一:异步编程的魅力
异步编程二:promise模式
异步编程三:reactor模式
异步编程四:协程
java程序员的kotlin课(一):环境搭建
java程序员的kotlin课程(二): 高阶函数与泛型的几个套路
java程序员的kotlin课(N):coroutines基础
java程序员的kotlin课(N+1):coroutines 取消和超时
java程序员的kotlin课(N+2):suspending函数执行编排
jvm-sandbox-repeater http回放的“陷阱”与源码研读
欢迎大家关注我的,不常更新的公众号,与我保持联络: