|
|
51CTO旗下网站
|
|
移动端

WOT徐冬晨:JVM—Sandbox 基于JVM的非侵入式运行期AOP解决方案

身兼主持人和演讲人双重职责的徐冬晨轻松有活力的开场,为我们讲述了JVM—Sandbox的产生背景以及它的优势所在,包括应用场景、核心技术、开源几个方面的内容。

作者:刘妮娜来源:51CTO|2018-06-29 13:24

【51CTO.com原创稿件】2018年5月18-19日,由51CTO主办的全球软件与运维技术峰会在北京召开。来自全球企业的技术精英汇聚北京,畅谈软件技术前沿,共同探索运维技术的新边界。而在本次大会上,除了众星云集的主论坛环节,12场分论坛更是各具特色,在19日下午的“微服务架构设计”分论坛上,来自阿里巴巴淘宝技术质量部测试研发工程师徐冬晨发表了精彩演讲。身兼主持人和演讲人双重职责的徐冬晨轻松有活力的开场,为我们讲述了JVM—Sandbox的产生背景以及它的优势所在,包括应用场景、核心技术、开源几个方面的内容。

JVM—Sandbox的产生背景

随着软件规模的扩大,系统功能的细分,要保证阿里巴巴整个系统稳定性,要做许多工具平台和监控体系,辛勤的开发测试人员都需要做哪些工作呢?徐冬晨举例说明,例如我们要做系统限流、流控、故障模拟、信息监控、链路跟踪、问题定位等等,最应该关心的是,系统架构升级之后,对基础业务有没有影响,测试者要寻求自动化测试的方法,实现自动化的业务回归。

对于写接口测试的测试工程师来说,他们更想完成的一种方式是线上录制、线下回放的方式进行业务回归,这样可以大大节省成本。如果要做这样的一个回归,其方法也是对方法的入参和返回值进行监控,或者是监控它整条链路上面会不会出问题。下面就是监控以及链路跟踪,以及精准回归。

徐冬晨列出了四个比较具体的场景,要保证它的稳定性的确需要做很多事情。当我们把这些东西做一个简单的抽象之后,上面的这些工具平台就做两件事情:

第一是方法的监听与环绕管控,第二是行链路信息的获取与统计。以方法的监听与环绕管控为例,这就是用java,用大家最熟悉的NOP。但是使用NOP也是有些问题的,如果我们要有一个统一的监控平台,监控系统代码与代码的比例也很重要。她看到过最夸张的一个系统,监控代码和业务代码的比例是1:2,就是1/3的代码都是监控代码,而且这种监控代码是比较笨重的,是因为要发散,才能够把它发上去,这就是问题的所在。

行链路方面,为了计算覆盖率,如果我们要维持系统的灵活度,就不能因为要做一个问题定位,要加一行日志,就重新做系统,我们在做稳定性平台配套工具的时候,需要具备三个特点:

第一:对于开发代码是无侵入的。

    第二:要实时生效,因为问题解决的时候,要保留现场,所以要实时生效。

    第三:动态可插拔。

要做成这样子,就需要一个动态字节码增强解决方案。如上面所说,无论故障演练、强弱依赖检测、流量录制回访、问题定位还是监控体系,如果我们每做这么一个工具平台,底层全部去实现一个动态字节码增强的话,投入的成本是很高的,是有学习门槛的。上面衍生出来的这个平台,最后都会作用到一个系统里面去,其实他们底层字节码增强,这段代码会不会相互干扰,都是问题。为了解决这些问题,为了屏蔽字节码增强的技术高门槛,为了降低研发和运营的成本,为了上层多个模块可以动态管理。我们就开发出JVM--Sandbox。

JVM—Sandbox的优势

JVM—Sandbox既有AOP通用API的便利,又有埋点的灵活,实时非侵入的AOP容器。它的功能方面,首先JVM—Sandbox是基于JVMTI技术规范,为观察和改变代码运行结果提供了即插即用模块接口的容器。JVM-Sandbox为AOP提供了一个新的实现方案——以插桩代替代理。

使用人群:使用字节码增强技术,进行工具开发、实现业务功能的开发、测试同学。

核心功能:首先它提供了一个字节码增强统一API。其次它提供了无切入的容器,它跟你的目标机器之间其实是隔离的。第三就是我们的容器管理。你可以在JVM—Sandbox基础上可以挂载多个模块,每个模块完成它自己的链路跟踪、问题定位这些功能是可以同时挂载的。

利用Sandbox可以实现哪些功能呢?抽象出来是入参的感知与改变。返回值的感知与改变以及抛异常。流程的控制,执行之前返回,执行之前重新构造新的一个结果对象进行返回,异常之后重新抛出异常或者直接返回一个正常的结果,它可以帮你做这些事情。徐冬晨向大家做了一个简单的介绍:

核心操作对象  

首先看核心操作对象,这是一个抽象的过程,我们已经在用的有一些开源的工具,包括定位工具、测试工具,我们抽象出来其实就是执行之前的观察和异常观察,还有执行之前的改变以及异常改变。其实这样抽象完之后,我们的核心事件是三个,比如说我们transform事件,三个环节正常流转和干预流转,以及行事件,行事件其实就是在每一个代码行后面加一个插装。

如何与目标进行隔离和通讯

那么,如何保证Sandbox和目标机器之间是相互隔离的呢?做法非常简单,用一句话概括的就是:破坏双亲委派机制和自定义ClassLoader完成类隔离。向Bootstrap ClassLoader注入一个Spy类来完成通讯。这个是最原始的双亲委派机制。

破坏双亲委派机制后,如果要加载一个类的时候,它会先去看当前的ClassLoader是否已经存在,如果没有加载的话,它会委派它的父亲,它的父ClassLoader去问,你是不是已经加载了,如果它也没有加载的话,再向上询问,一直询问到 Boots trap ClassLoader。这个是原生的双亲委派机制。

破坏后的双亲委派机制变成了什么?要挂载一个类,它会先看我当前的ClassLoader是不是加载了,如果没加载,它会让当前的ClassLoader尝试着去加载,也就是它不再向它的父类去询问,除非它无法加载的时候,它才会去问它的父ClassLoader说,你是不是已经加载了,如果父ClassLoader也没有加载的话,它会让父ClassLoader尝试着去加载。这样就完成了我的目标应用之间与Sandbox之间的隔离。

其实Sandbox在启动的时候会做一些事件,它会为每一个Module,就是上层挂载的Module,以及Sandbox,每个Module都会去给它新建一个ClassLoader,Sandbox自己也会给它新建一个ClassLoader。这样的话我们就完成了Sandbox与Module之间,以及Module与Module之间,以及他们与目标应用之间的隔离。

通讯其实就是我们在 Boots trap ClassLoader里面会注入一个Spy类,这个Spy类负责目标应用与Sandbox之间的通讯,不是特别直观。

如何做到动态插拔

谈到如何去实现动态可插拔,徐冬晨用一句话概括:transform方法形变原生字节码,事件监听表管理模块。为什么要有这块,其实不管是对于一个系统来讲,我们将系统上面attach一个东西,我们最关心的是,我能不能还原,有能力再恢复回去。你增加的一些东西,你增加Sandbox和这些模块之后,对我的系统到底它是怎么去作用上去的,它在哪里发生了形变,它的怎么作用上去的,我系统还能不能还原。

这样的话,其实这幅图就是表现的是这样的一件事情,我们先看一下我们的形变发生在哪里,对JVM已经加载的类进行过滤(过滤器由Module告知sandbox),找到需要形变的类。拿到我要形变的类之后,他会通过一个形变通道,通过这个形变通道,形变通道上面都有哪些事情,都有哪些形变,就是由我们Sandbox加载的各个Module来决定的。

这边相当于是一个事件监听表,这个Module对这个类发生了一次形变。如果我新增加一个Module会怎么样,所有的类会重新过滤一次,对Module指定重新加载形变。如果我减少一个Module。同样的,需要先过滤出Module指定的类,然后进行形变。这样的话,从这个上面我们可以看到,如果我把Sandbox上面所有的模块全部卸载掉之后,整个通道就是没有形变的,没有形变的话,就是一个class而变成这个数,然后再变成一个class,其实它就是没有形变,整个代码其实也就还原了。

在使用Sandbox过程中,如果你只挂载Sandbox,本身对你原码是没有影响的,如果你在Sandbox基础上挂载了Module,Module决定了你影响了哪些类和哪些方法。当你把一个Module卸载掉之后,整个形变也就消失了,这是动态可插拔来完成的。

如上图,这是JVM-Sandbox的一个整体的架构,这个里面比较底层就是在JVMTI架构体系上面去构建的,做了一些代码编织的框架。我们可以对它进行方法调用的环绕编织,方法流程的干预,方法路径的编织,这样的一些过程。沙箱会进行事件分发,事件监听,事件注销和事件的一些处理。这样其实就完成了,我们完成了模块的管理,上层我们会做一些模块管理的事情。

我们看这个里面,多出来的一块其实这一部分,这部分就是在Sandbox里面,它有个HTTP服务器,它的作用是整个Sandbox挂起之后,你的模块是需要挂载、卸载、激活、启动这些操作时,服务器来控制它。当时比较方便的一种方式就是HTTP企图去控制,所以它里面增加了HTTP的服务器。所以你在Sandbox挂载之后,上层的模块,其实都可以通过HTTP请求然后加以控制,去控制它的启动、卸载和加载这样的一些事情。

Sandbox本身是已经开源的,能够拿到它所有的原代码。我们希望是有更多的同学,能够想到更多的应用场景,并且开源出来供大家使用。

本次WOT峰会讲师演讲稿件由51CTO采编整理,如欲了解更多,敬请登录WWW.51CTO.COM进行查看。

【51CTO原创稿件,合作站点转载请注明原文作者和出处为51CTO.com】
【责任编辑:刘妮娜 TEL:(010)68476606】


点赞 0
分享:
大家都在看
猜你喜欢

热门职位+更多

读 书 +更多

程序设计实践双语版

程序设计实践并不只是写代码。程序员必须评论各种折衷方案,在许多可能性之中做出选择、排除错误、做测试和改进程序性能,还要维护自己或其...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊