快速了解阿里开源中间件动态非侵入AOP解决方案 JVM-Sandbox
Posted 后端开发那点事儿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速了解阿里开源中间件动态非侵入AOP解决方案 JVM-Sandbox相关的知识,希望对你有一定的参考价值。
JVM-Sandbox 简介
JVM-Sandbox 是一个 JVM 沙箱容器,一种 JVM 的非侵入式运行期 AOP 解决方案。由纯Java编码完成,基于JVMTI技术规范,为观察和改变代码运行结果提供了即插即用模块接口的容器。在阿里巴巴内部使用广泛,现已开源。
在常见的AOP框架实现方案中,有静态编织和动态编织两种。静态编织发生在字节码生成时根据一定框架的规则提前将AOP字节码插入到目标类和方法中,实现AOP。
动态编织则允许在JVM运行过程中完成指定方法的AOP字节码增强.常见的动态编织方案大多采用重命名原有方法,再新建一个同签名的方法来做代理的工作模式来完成AOP的功能(常见的实现方案如CgLib)。对被代理的目标类需要进行侵入式改造。比如:在Spring中必须是托管于Spring容器中的Bean。目标代理方法在启动之后即固化,无法重新对一个已有方法进行AOP增强。
还有一些实现AOP的方式是通过类似热部署的方式完成,但现有的热部署实现方案也存在一些应用边界:性能折损巨大、对JVM存在侵入性、必须启动时显式开启。JVM-Sandbox 基于此通过JDK6所提供的Instrumentation-API实现了利用HotSwap技术在不重启JVM的情况下实现对任意方法的AOP增强。而且性能开销还在可以接受的范围之内。
JVM-Sandbox 一共由三大核心功能组件构成。
1、代码编织组件:负责完成预设代码的重写和生效;
2、事件处理分发组件:负责完成事件的分发和方法流控控制的执行;
3、模块管理组件:负责控制和管理沙箱的各个模块。
在 JVM-Sandbox 的世界观中,任何一个Java方法的调用都可以分解为BEFORE、RETURN和THROWS三个环节,由此在三个环节上引申出对应环节的事件探测和流程控制机制。
基于BEFORE、RETURN和THROWS三个环节事件,可以完成很多类AOP的操作。
1、可以感知和改变方法调用的入参;
2、可以感知和改变方法调用返回值和抛出的异常;
3、可以改变方法执行的流程。
方法执行时可以实现以下功能:
1、在方法体执行之前直接返回自定义结果对象,原有方法代码将不会被执行;
2、在方法体返回之前重新构造新的结果对象,甚至可以改变为抛出异常;
3、在方法体抛出异常之后重新抛出新的异常,甚至可以改变为正常返回;
为了实现沙箱模块的动态热插拔,容器客户端和沙箱动态可插拔容器采用HTTP协议进行通讯,底层用Jetty8作为HTTP服务器。JVM-Sandbox 的底层提供了一个HTTP-SERVER(Jetty实现),通过HTTP协议完成sandbox.sh和沙箱的控制交互,同时也给各个模块提供了基于HttpServlet和WebSocket规范的API,各模块可以复用沙箱完成各自模块的控制与交互。
JVM-Sandbox 的特点
沙箱提供了即时加载ATTACH和启动加载AGENT两种启动方式,两种方式均能正确完成沙箱启动及其模块的加载。
ATTACH方式启动
在不需要重启目标JVM的情况下,无感、动态的完成沙箱容器的启动和方法切面的植入
AGENT方式加载
目标JVM启动时完成沙箱容器的启动,并在整个应用启动过程中完成方法切面的植入
沙箱容器采用传统的C/S架构模式,通讯协议考虑到可能要部署到内网,需要NAT网关转发,所以采用了HTTP协议。
HTTP-CLIENT:sandbox.sh
HTTP-SERVER:沙箱容器(jetty8实现)
在对每个目标JVM进程启动沙箱容器时,容器会主动向目标JVM植入一个agent,容器加载的多个module共享这个agent。
沙箱通过自定义的SandboxClassLoader破坏了双亲委派的约定,实现了和观察应用的类隔离。所以不用担心加载沙箱会引起应用的类污染、冲突。
各模块之间类通过ModuleClassLoader实现了各自的独立,达到模块之间、模块和沙箱之间、模块和应用之间互不干扰。
通过向Bootstrap ClassLoader中注入Spy类,完成观察应用与JVM-Sandbox的通讯。沙箱容器会将事件分发给各个Module,完成容器与Module之间的通讯。
插入Spy类到字节码中,Spy方法中反射调用JVM-Sandbox的方法。编织完成后,整个代码执行流程将会变成为下图。
JVM-Sandbox 在阿里集团的应用
基于 JVM-Sandbox 改造后的故障演练平台,通用性强,所有基于 JVM 启动的系统均支持,极大的拓展了故障演练的范围,故障演练已达到集团级部署。
17 年强弱依赖自动化检测平台诞生。它提供了依赖检测、强弱分析、依赖扫描、故障注入等多种能力,底层能力基于 JVM-Sandbox 在 1 周内完成功能开发。利用其模块容器的特性,将前人开发的模块与新增模块一起挂载共同工作,完成平台功能。
强弱依赖梳理方面,承载了淘宝的系统强弱依赖梳理工作,260+ 个应用一键接入系统,并实现了 0 人工成本的自动化、智能化梳理。
在 JVM-Sandbox 基础上开发了一个 SS 模块,相当于一个录音机 + 回放机, 在调用中间件的时候, 顺序录制下了我们的中间件请求, 并且存储这份‘磁带’到服务器上。当我们需要隔离回放的时候, 将这份‘磁带’找到, 并且在需要的时候直接从‘磁带’读取, 并不需要真实地请求我们的中间件, 这样就保证了我们的读、写接口也能做到可重复使用,从而实现服务端的隔离回放。
线上录制隔离回放不仅极大的缩短的业务回归的耗时,把业务测试同学从繁琐的数据准备和接口自动化脚本的编写过程中解放出来,而且极大的拓展了覆盖范围,使回归的范围更贴近用户,且场景更丰富。
服务端录制隔离回放机制诞生之后,虽然有效的提升了覆盖范围,降低了自动化脚本的人工投入,但是也带来了新的问题。线上录制的场景是海量的,单个系统都可以达到万级、十万级甚至百万级别的录制,这些录制的场景中,存在大量的重复场景,如何识别重复场景,实现有效、精准的回放,成为新的待解决问题。
17 年在 JVM-Sandbox 的基础上,利用 LineEvnet 实现了行链路识别和标记,有效的提升了回放的精准度和效率。
以上是关于快速了解阿里开源中间件动态非侵入AOP解决方案 JVM-Sandbox的主要内容,如果未能解决你的问题,请参考以下文章
阿里开源动态非侵入 AOP 解决方案 JVM-Sandbox | 软件推介
阿里巴巴正式开源自研动态非侵入AOP解决方案:JVM-Sandbox