JavaAgent-SandBox

简介: 1.前言 之前初步学习了javaAgent,并做了一份总结《JavaAgent学习笔记》。然后在看到《JVM-Sandbox 基于JVM的非侵入式运行期AOP解决方案》之后,接触到了集团的sandBox。并尝试使用这种有真正应用场景的运行时AOP框架。 2.SandBox简介 sandBox是集团开发的一种非侵入式的运行时AOP解决方案,它能动态地将你要实现的代码模块打包编织到目标代码中,实

1.前言

之前初步学习了javaAgent,并做了一份总结《JavaAgent学习笔记》。然后在看到《JVM-Sandbox 基于JVM的非侵入式运行期AOP解决方案》之后,接触到了集团的sandBox。并尝试使用这种有真正应用场景的运行时AOP框架。

2.SandBox简介

sandBox是集团开发的一种非侵入式的运行时AOP解决方案,它能动态地将你要实现的代码模块打包编织到目标代码中,实现事件的监听、切入与代码增强。我们一般可以使用以下场景:

  • 线上故障定位
  • 线上系统流控
  • 线上故障模拟
  • 方法请求录制和结果回放
  • 动态日志打印
  • 安全信息监测和脱敏
  • 行链路计算和覆盖率统计

详细的介绍可以阅读这篇篇文章《JVM-Sandbox 基于JVM的非侵入式运行期AOP解决方案》,个人简单总结以下几点:

2.1 AOP切入方式

SandBox围绕“EventListener事件监听”、“Filter目标过滤”、“onEvent事件处理”来实现AOP的切入。

首先,SandBox将事件分类为BEFORE、 RETURN和 THROWS三个环节事件,除此之外还有个LINE。然后观察者通过监听这几个环节的事件进行流转和干预

                                        +-------+
                                        |       |
 +========+  <return>             +========+    | <return immediately>
 |        |  <return immediately> |        |    |
 | BEFORE |---------------------->| RETURN |<---+
 |        |                       |        |
 +========+                       +========+
     |                              |    ^
     |         <throws immediately> |    |
     |                              |    | <return immediately>
     |                              v    |
     |                            +========+
     |                            |        |
     +--------------------------->| THROWS |<---+
                    <throws>      |        |    |
        <throws immediately>      +========+    | <throws immediately>
                                        |       |
                                        +-------+

     2.2 沙箱隔离与通讯

1.SandBox与Tomcat同级加载,并且Tomcat是一定程度破坏了双亲委派机制的,实现各个WebApp之前的隔离。这种与Tomcat同级加载的方式,一定程度保证了类的隔离,防止冲突与污染。

2.由Bootstrap加载的Spy类实现了SandBox与被观察的应用的事件通信,然后SandBox将这些事件信息分发给对应的Module进行处理。

2.3 动态代码织入

1.使用过滤器在JVM中找到目标类的数据信息

2.trasform方法形变原生字节码,插入Spy类到字节码中,通过Spy方法中反射调用JVM-Sandbox的方法。

3. 简单的SandBox功能实现

3.1启动SandBox

现在集团的服务器一般都集成了SandBox的插件环境,切换到/home/staragent/plugins/JVM-Sandbox.src/JVM-Sandbox.cur/sandbox/bin目录,找到启动脚本

找到观察的java应用进程,然后进行SandBox的attach。使用指令 ./sandbox.sh -p 进程号(建议使用admin用户执行,否则会遇到一些问题)

挂载成功后,会打印以下内容,其中USER_MODULE_LIB目录是要将自己的Module挂载的目录。将自己打包成jar形式的Module通过scp或oss等方式,上传到该目录后,执行./sandbox.sh -p 进程号 -f 刷新Module,

刷新后,我们看一下Module是否挂载成功

3.2 Module模块开发

SandBox底层提供了一个HTTP-SERVER(Jetty),通过HTTP协议完成sandbox.sh和沙箱的控制交互,同时也给各个模块提供了基于HttpServlet和WebSocket规范的API,各模块可以复用沙箱完成各自模块的控制与交互。

1.首先需要在resource的META-INF.servicesn内配置一个文件,配置一个Module的入口。

2.编写Module类

需要实现Module, ModuleLifecycle这2个接口,添加@Information注释,然后编写具体的增强代码。这里使用了@Http,通过指令,实现退这些方法的调用。这里需要自己写Filter与EventListener,进行目标对象的过滤与监听,还有事件处理。

需要moduleEventWatcher加载这个监听器,然后使用moduleContraller激活这个监听器。

@Information(version = GlobalConfig.VERSION, author = "lixian.wlx@alibaba-inc.com",
    id = GlobalConfig.NAME, isActiveOnLoad = false)
public class DrillModule implements Module, ModuleLifecycle {

    @Resource
    private ModuleController moduleController;

    @Resource
    private ModuleEventWatcher moduleEventWatcher;

    @Override
    public void onLoad() throws Throwable {
        //TODO
    }

    @Override
    public void loadCompleted() {
        //TODO
    }

    @Override
    public void onUnload() throws Throwable {
        //TODO
    }

    @Override
    public void onActive() throws Throwable {
        //TODO
    }

    @Override
    public void onFrozen() throws Throwable {
        //TODO
    }

    @Http("/mps")
    public void mockProvideSentinel(HttpServletRequest request, HttpServletResponse response) throws Throwable {
        //获取入参
        MockConfigModel mockConfigModel = null;

        String mockClassName = null;
        String mockMethodName = null;
        String uniqueCode = null;
        PrintWriter writer = null;
        try {
            mockConfigModel = processMockRequest(request);
            mockClassName = mockConfigModel.getMockClassName();
            mockMethodName = mockConfigModel.getMockMethodName();
            uniqueCode = buildUniqueCode(mockConfigModel);
            writer = new PrintWriter(response.getWriter(), true);
        } catch (Throwable throwable) {
            logger.error("mockProvideSentinel get param error {} of {}", mockMethodName, mockClassName, throwable);
        }
        if (methodMap.get(uniqueCode) != null) {
            writer.write("mockProvideSentinel fail mockModel:{" + uniqueCode +"} has exist!");
            writer.close();
            logger.warn("mockProvideSentinel fail {} of {} has exist!", mockMethodName, mockClassName);
            return;
        }
        //实现aop切入,返回watcherId
        try {
            int watcherId = moduleEventWatcher.watch(new Hsf2InvokeFilter(), new HsfListener(mockClassName, mockMethodName, new HsfInvokeSentinelHandler()), Type.BEFORE);
            //生成mock业务
            watcherIds.add(watcherId);
            methodMap.put(uniqueCode, watcherId);
            watcherMap.put(watcherId, uniqueCode);
            moduleController.active();
            //返回mock结果
            writer.write(watcherId);
            writer.close();
            logger.info("mockProvideSentinel success mock {} of {}. watcherId: {}", mockMethodName, mockClassName, watcherId);
        } catch (ModuleException e) {
            writer.write(e.toString());
            writer.close();
            logger.error("mockProvideSentinel error {} of {}", mockMethodName, mockClassName, e);
        }

    }    

}

3. 以上代码是模拟HSF的客户端对某个API的限流

./sandbox.sh -p 进程号 -d 'tfdrill-module/mps?mockClassName=EmployeeAPI',  针对这个api进行限流

4. 总结

暂时,我们利用SandBox实现了简单的故障模拟,后续还有跟多的功能开发出来

目录
相关文章
|
缓存 Java Shell
【alibaba/jvm-sandbox#06】事件监听的关键设计
介绍jvm-sandbox中事件机制的设计,通过用事件Id与事件之间的映射关系进行解耦,通过Spy类的静态方法携带事件Id进行核心事件逻辑的埋点注入
694 0
|
JSON Linux 开发工具
「译文」给讨厌 YAML 的人的 10 个写 YAML 的建议
「译文」给讨厌 YAML 的人的 10 个写 YAML 的建议
|
1月前
|
存储 消息中间件 Kafka
Confluent 首席架构师万字剖析 Apache Fluss(二):核心架构
原文:https://jack-vanlightly.com/blog/2025/9/2/understanding-apache-fluss 作者:Jack Vanlightly 翻译:Wayne Wang@腾讯 译注:Jack Vanlightly 是一位专注于数据系统底层架构的知名技术博主,他的文章以篇幅长、细节丰富而闻名。目前 Jack 就职于 Confluent,担任首席技术架构师,因此这篇 Fluss 深度分析文章,具备一定的客观参考意义。译文拆成了三篇文章,本文是第二篇。
279 19
|
Java jvm-sandbox 容器
【alibaba/jvm-sandbox#05】沙箱事件详解
alibaba/jvm-sandbox设计了完善且复杂的沙箱事件,用于实现事件探测和流程控制机制。但不建议对于同一个类、同一个方法多次增强
922 0
|
网络协议 Java 测试技术
性能工具之常见流量复制工具
我们把用户访问系统造成的数据传输定义为流量,那么在用户访问系统的过程中,我们可以把进入和流出的数据复制下来,进行保存,待后续使用,即离线模式,或者转发到一个新的服务器,立即使用,即在线模式。
773 2
性能工具之常见流量复制工具
|
开发工具 git
git将一个远程分支的部分修改提交到另一个远程分支
git将一个远程分支的部分修改提交到另一个远程分支
1168 1
|
传感器 C++
计算机网络:数据链路层之差错控制、奇偶校验码、CRC循环冗余码、海明码
计算机网络:数据链路层之差错控制、奇偶校验码、CRC循环冗余码、海明码
758 0
|
安全 JavaScript 应用服务中间件
Nginx 跨域解决方案
跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器,它允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。 跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是GET以外的 HTTP 请求
|
Arthas 监控 安全
浅谈阿里开源JVM Sandbox(内含代码实战)
浅谈阿里开源JVM Sandbox(内含代码实战)
47721 6
浅谈阿里开源JVM Sandbox(内含代码实战)
|
弹性计算 物联网 Serverless
阿里云备案必须买服务器吗?不一定
阿里云支持备案云产品列表(不只是云服务器),阿里云服务器可用于网站域名备案,事实上不只是云服务器,阿里云支持备案的云产品有很多,例如虚拟主机、ENSIPv6转换服务、轻量应用服务器、物联网套餐包、建站市场产品、函数计算套餐包及企业商城LinkedMall也支持在阿里云备案。阿里云支持备案的云产品及限制条件如下:
3251 0