jvm-sandbox demo

 

一、前言

在开始之前,我们先来模拟一下以下的场景:

小李:“小明,你的接口没有返回数据,麻烦帮忙看一下?”

小明:“我这边的数据也是从别人的服务器中拿到的,但是我不确定是因为逻辑处理有问题导致没有结果,还是因为我依赖的服务有问题而没有返回结果,我需要确认一下。”

小明:“哎呀,线上没有日志,我需要加个日志上个线。”

30 分钟之后……

小明:“不好意思,日志加错地方了……稍等……”

接来下隆重登场的就是本文的主角 JVM SandBox 了。基于 JVM SandBox,我们可以很容易地做到在不重新部署应用的情况下,给指定的某些类的某些方法加上日志功能。当然,动态加日志仅仅是 JVM SandBox 可以应用的一个小小的场景,JVM SandBox 的威力远不在于此。那么,JVM SandBox 是什么?JVM SandBox 从哪里来?JVM SandBox 怎么用?本文在第二章会回答这几个问题,如果你跟我一样对 JVM SandBox 的底层实现原理感兴趣,特别是 JVM 相关部分,那么第三章有相关的内容;如果你只想了解 JVM SandBox 自身具有哪些特性,以及 JVM SandBox 是如何设计实现的,那么可以跳过第三章,直接阅读第四章;最后,在第五章会简单地介绍其他两个可以应用 JVM SandBox 的场景。

二、JVM SandBox 简介

2.1 AOP

在介绍 JVM SandBox 之前,我们先来回顾一下 AOP 技术。

AOP(面向切面编程,Aspect Oriented Programming)技术已被业界广泛应用,其思想是面向业务处理过程的某个步骤或阶段进行编程,这个步骤或阶段被称为切面,其目的是降低业务逻辑的各部分之间的耦合,常见的 AOP 实现基本原理有两种:代理和行为注入。

1)代理模式
在代理模式下,我们会创建一个代理对象来代理原对象的行为,代理对象拥有原对象行为执行的控制权,在这种模式下,我们基于代理对象在原对象行为执行的前后插入代码来实现 AOP。

JVM  SandBox的技术原理与应用分析

图 2-1 代理模式

2)行为注入模式
在行为注入模式下,我们不会创建一个新的对象,而是修改原对象,在原对象行为的执行前后注入代码来实现 AOP。

JVM  SandBox的技术原理与应用分析

图 2-2 行为注入模式

2.2 JVM SandBox

JVM SandBox 是阿里开源的一款 JVM 平台非侵入式运行期 AOP 解决方案,本质上是一种 AOP 落地形式。那么可能有同学会问:已有成熟的 Spring AOP 解决方案,阿里巴巴为什么还要“重复造轮子”?这个问题要回到 JVM SandBox 诞生的背景中来回答。在 2016 年中,天猫双十一催动了阿里巴巴内部大量业务系统的改动,恰逢徐冬晨(阿里巴巴测试开发专家)所在的团队调整,测试资源保障严重不足,迫使他们必须考虑更精准、更便捷的老业务测试回归验证方案。开发团队面临的是新接手的老系统,老的业务代码架构难以满足可测性的要求,很多现有测试框架也无法应用到老的业务系统架构中,于是需要新的测试思路和测试框架。

三.使用

3.1下载

安装jvm-sandBox

# 下载最新版本的JVM-SANDBOX
wget http://ompc.oss-cn-hangzhou.aliyuncs.com/jvm-sandbox/release/sandbox-stable-bin.zip

# 解压
unzip sandbox-stable-bin.zip

3.2安装

# 进入sandbox执行脚本
cd sandbox/bin

# 项目进程id 55731(使用jps命令查看或者ps命令)
./sandbox.sh -p 55714


rong:bin rss$ ./sandbox.sh -p 55714
                    NAMESPACE : default
                      VERSION : 1.3.3
                         MODE : ATTACH
                  SERVER_ADDR : 0.0.0.0
                  SERVER_PORT : 54584
               UNSAFE_SUPPORT : ENABLE
                 SANDBOX_HOME : /Users/rss/jvm-sendbox/sandbox/bin/..
            SYSTEM_MODULE_LIB : /Users/rss/jvm-sendbox/sandbox/bin/../module
              USER_MODULE_LIB : /Users/rss/jvm-sendbox/sandbox/sandbox-module;~/.sandbox-module;
          SYSTEM_PROVIDER_LIB : /Users/rss/jvm-sendbox/sandbox/bin/../provider
           EVENT_POOL_SUPPORT : DISABLE
出现以上信息,表示sandbox 启动成功

3.3使用

切面项目打包到sandbox/sand-module目录下,如下图

切面项目代码:

监控目标项目

类:com.rss.gateway.controller.Demo

方法:sandBoxDemo


import com.alibaba.jvm.sandbox.api.Information;
import com.alibaba.jvm.sandbox.api.Module;
import com.alibaba.jvm.sandbox.api.annotation.Command;
import com.alibaba.jvm.sandbox.api.listener.ext.Advice;
import com.alibaba.jvm.sandbox.api.listener.ext.AdviceListener;
import com.alibaba.jvm.sandbox.api.listener.ext.EventWatchBuilder;
import com.alibaba.jvm.sandbox.api.resource.ModuleEventWatcher;
import lombok.extern.slf4j.Slf4j;
import org.kohsuke.MetaInfServices;

import javax.annotation.Resource;

@MetaInfServices(Module.class)
@Information(id = "gateway")// 模块名,在指定挂载进程后通过-d指定模块=
@Slf4j
public class MySandBoxModule implements Module {

    @Resource
    private ModuleEventWatcher moduleEventWatcher;

    @Command("checkDemo")
    public void checkDemo() {
        new EventWatchBuilder(moduleEventWatcher)
                //切入目标类
                .onClass("com.rss.gateway.controller.SandBoxDemo")
                //切入目标方法
                .onBehavior("sandBoxDemo")
                .onWatch(new AdviceListener() {
                    //对方法执行之前执行
                    @Override
                    protected void before(Advice advice) {
                        //在这里可以做很多事情,demo只打印了日志信息

                        System.out.println("sandbox切入");
                        //获取方法的所有参数
                        Object[] parameters = advice.getParameterArray();
                        if (parameters != null) {
                            for (Object obj : parameters) {
                                System.out.println("参数类型:" + obj.getClass().getName() + "!!!!!!!");
                                System.out.println("参数值:" + obj + "!!!!!!!");
                            }
                        }
                    }
                });
    }
}

执行 使用自定义module执行

./sandbox.sh -p 55714 -d 'gateway/checkDemo'
 

目标项目中的方法如下代码:

@RestController
@Slf4j
public class SandBoxDemo {

    @RequestMapping(value = "/sandBoxDemo")
    public void sandBoxDemo(HttpServletRequest request, String data)throws Exception{
        log.info("我是被切入的目标方法" + data);
    }

}

访问:http://localhost:20977/sandBoxDemo?data=111111

结果如下:

17:10:10.572 [http-nio-20977-exec-2] INFO com.online.test.MySandBoxModule - sandbox切入成功!!!!!!
17:10:10.572 [http-nio-20977-exec-2] INFO com.online.test.MySandBoxModule - 参数类型为:org.springframework.web.multipart.support.StandardMultipartHttpServletRequest!!!!!!!
17:10:10.572 [http-nio-20977-exec-2] INFO com.online.test.MySandBoxModule - 参数值为:org.springframework.web.multipart.support.StandardMultipartHttpServletRequest@499a1054!!!!!!!
17:10:10.572 [http-nio-20977-exec-2] INFO com.online.test.MySandBoxModule - 参数类型为:java.lang.String!!!!!!!
17:10:10.572 [http-nio-20977-exec-2] INFO com.online.test.MySandBoxModule - 参数值为:111111!!!!!!!
17:10:10.572 [http-nio-20977-exec-2] INFO com.online.test.MySandBoxModule - 我是被切入的目标方法111111

3.4退出

直接停止目标(被切入的项目)项目,不建议用这种方式

用命令退出

./sandbox.sh -p 55714 -S

四.其他

其他常用命令

#卸载沙箱
./sandbox.sh -p 55714 -S
#查询沙箱
./sandbox.sh -p 55714 -l
#刷新沙箱
./sandbox.sh -p 55714 -F
#使用自定义module执行
./sandbox.sh -p 55714 -d 'gateway/checkDemo'

#日志配置及查看
#配置文件在    /sandbox/rss/sandbox-logback.xml
#默认日志路径    ~/logs/sandbox/sandbox.log

五.讨论话题:

怎样更优雅的监控项目:

1.实时监控项目PID

2.获取方法的更新

3.热启动

 

 

参考文档

1.https://www.infoq.cn/article/TSY4lGjvSfwEuXEBW*Gp
2.https://github.com/alibaba/jvm-sandbox

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值