• 阿里开源-JVM-SandBox


    阿里开源-JVM-SandBox


    阿里开源-JVM-SandBox


    一、JVM-SandBox能解决什么问题?

    线上故障定位
    线上系统流控
    线上故障模拟
    方法请求录制和结果回放
    动态日志打印
    安全信息监测和脱敏
    JVM-SANDBOX还能帮助你做很多很多,取决于你的脑洞有多大了。

    二、使用步骤

    1.开源代码

    开源代码库: https://github.com/alibaba/jvm-sandbox
    
    • 1

    2.使用示例

    修复破损的时钟(gitlab 示例):

    【准备阶段】
    我们定义了一个钟,期望可以实现每隔一定的时间进行报时(gitlab 代码)。

    package com.taobao.demo;
    
    /**
     * 报时的钟
     */
    public class Clock {
    
        // 日期格式化
        private final java.text.SimpleDateFormat clockDateFormat
                = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
        /**
         * 状态检查
         */
        final void checkState() {
            throw new IllegalStateException("STATE ERROR!");
        }
    
        /**
         * 获取当前时间
         *
         * @return 当前时间
         */
        final java.util.Date now() {
            return new java.util.Date();
        }
    
        /**
         * 报告时间
         *
         * @return 报告时间
         */
        final String report() {
            checkState();
            return clockDateFormat.format(now());
        }
    
        /**
         * 循环播报时间
         */
        final void loopReport() throws InterruptedException {
            while (true) {
                try {
                    System.out.println(report());
                } catch (Throwable cause) {
                    cause.printStackTrace();
                }
                Thread.sleep(1000);
            }
        }
    
        public static void main(String... args) throws InterruptedException {
            new Clock().loopReport();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    运行代码
    很明显,这个钟的实现有问题,运行起来没有正确的报时,但却一直在报异常!
    问题分析
    问题出在了checkState()方法上,这个方法中抛出了异常。接下来我们通过构建一个沙箱模块作为例子,修复这个损坏的钟!

    解决方案
    如果能直接修改checkState()方法的执行逻辑,让其不再抛异常,而是直接返回,那么一切就迎刃而解。但如何在不修改目标代码、不重启目标应用的情况下实现这个功能呢?
    【修复阶段】
    创建一个Java工程
    1、pom 文件 引入sandbox 依赖

    
    
        4.0.0
        
            org.springframework.boot
            spring-boot-starter-parent
            2.5.4
             
        
        com.example
        box-mock
        0.0.1-SNAPSHOT
        box-mock
        Demo project for Spring Boot
        
            1.8
        
        
            
                com.alibaba.jvm.sandbox
                sandbox
                1.3.1
                pom
            
            
            
                com.alibaba.jvm.sandbox
                sandbox-api
                1.3.1
                provided
            
            
            
                com.alibaba.jvm.sandbox
                sandbox-common-api
                1.3.1
            
            
            
                com.alibaba.jvm.sandbox
                sandbox-core
                1.3.1
                
                    
                        com.sun
                        tools
                    
                
            
    
            
                org.springframework.boot
                spring-boot-starter
            
    
            
                org.springframework.boot
                spring-boot-starter-test
                test
            
            
                org.kohsuke.metainf-services
                metainf-services
                1.8
            
        
    
        
            
            
                
                    org.apache.maven.plugins
                    maven-compiler-plugin
                    3.1
                    
                        1.8
                        1.8
                    
                
                
                    maven-assembly-plugin
                    
                        
                            
    
                            
                        
                        
                            jar-with-dependencies
                        
                    
                    
                    
                        
                            make-assemble
                            package
                            
                                single
                            
                        
                    
                
            
        
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107

    2、编写你要实现的代码逻辑

    package com.alibaba.jvm.sandbox.demo;
    
    import com.alibaba.jvm.sandbox.api.Information;
    import com.alibaba.jvm.sandbox.api.Module;
    import com.alibaba.jvm.sandbox.api.ProcessController;
    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 org.kohsuke.MetaInfServices;
    
    import javax.annotation.Resource;
    
    /***
    * 方式一 实现 Module
    **/
    @MetaInfServices(Module.class)
    @Information(id = "broken-clock-tinker")
    public class BrokenClockTinkerModule implements Module {
    
        @Resource
        private ModuleEventWatcher moduleEventWatcher;
    
        @Command("repairCheckState")
        public void repairCheckState() {
    
            new EventWatchBuilder(moduleEventWatcher)
                    .onClass("com.taobao.demo.Clock")
                    .onBehavior("checkState")
                    .onWatch(new AdviceListener() {
    
                        /**
                         * 拦截{@code com.taobao.demo.Clock#checkState()}方法,当这个方法抛出异常时将会被
                         * AdviceListener#afterThrowing()所拦截
                         */
                        @Override
                        protected void afterThrowing(Advice advice) throws Throwable {
                            
                            // 在此,你可以通过ProcessController来改变原有方法的执行流程
                            // 这里的代码意义是:改变原方法抛出异常的行为,变更为立即返回;void返回值用null表示
                            ProcessController.returnImmediately(null);
                        }
                    });
    
        }
    
    }
    ###############分割线#######################
    
    package com.example.boxmock.mock;
    
    import com.alibaba.jvm.sandbox.api.Information;
    import com.alibaba.jvm.sandbox.api.LoadCompleted;
    import com.alibaba.jvm.sandbox.api.Module;
    import com.alibaba.jvm.sandbox.api.ProcessController;
    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 org.kohsuke.MetaInfServices;
    
    import javax.annotation.Resource;
    
    /**
     * 方式二 实现 Module, LoadCompleted
     * Created on 2022-03-13
     */
    
    @MetaInfServices(Module.class)
    @Information(id = "broken-clock-tinker")
    public class BrokenClockTinkerModule  implements Module, LoadCompleted {
        @Resource
        private ModuleEventWatcher moduleEventWatcher;
    
        @Override
        public void loadCompleted() {
            new EventWatchBuilder(moduleEventWatcher)
                    .onClass("com.taobao.demo.Clock")
                    .onBehavior("checkState")
                    .onWatch(new AdviceListener() {
    
                        /**
                         * 拦截{@code com.taobao.demo.Clock#checkState()}方法,当这个方法抛出异常时将会被
                         * AdviceListener#afterThrowing()所拦截
                         */
    
                        @Override
                        protected void after(Advice advice) throws Throwable {
                            ProcessController.returnImmediately(true);
                        }
    
                    });
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    方式一、方式二区别在于后面启动JVM-sanbox 方式不同

    3、修复时钟

    3.1、编译部署clock-tinker模块 运行命令完成打包

    mvn clean package
    
    • 1

    3.2、下载并安装最新版本阿里SandBox包:

    下载地址:https://ompc.oss.aliyuncs.com/jvm-sandbox/release/sandbox-stable-bin.zip
    解压: unzip sandbox-stable-bin.zip
    
    • 1
    • 2

    3.3、将修复代码打好的包复制到解压后的 sandbox/sandbox-module/目录下

    cp target/****-SNAPSHOT-jar-with-dependencies.jar /sandbox/sandbox-module/

    3.4 查看 报错的 Clock 代码的 进程号:

    命令: jps 
    
    • 1

    在这里插入图片描述3.5 启动沙箱
    假设目标进程号:64927
    启动沙箱 进入sandbox/bin 执行启动脚本

    ./sandbox.sh -p 64927
    
    
                  NAMESPACE : default
                    VERSION : 1.2.0
                       MODE : ATTACH
                SERVER_ADDR : 0.0.0.0
                SERVER_PORT : 56854
             UNSAFE_SUPPORT : ENABLE
               SANDBOX_HOME : /Users/vlinux/opt/sandbox
          SYSTEM_MODULE_LIB : /Users/vlinux/opt/sandbox/module
            USER_MODULE_LIB : ~/.sandbox-module;
        SYSTEM_PROVIDER_LIB : /Users/vlinux/opt/sandbox/provider
         EVENT_POOL_SUPPORT : DISABLE
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    查看模块

    ./sandbox.sh -p 64229 -l
    
    
    broken-clock-tinker ACTIVE  LOADED  0  0  UNKNOW_VERSION  UNKNOW_AUTHOR
    sandbox-info        ACTIVE  LOADED  0  0  0.0.4           luanjia@taobao.com
    sandbox-module-mgr  ACTIVE  LOADED  0  0  0.0.2           luanjia@taobao.com
    sandbox-control     ACTIVE  LOADED  0  0  0.0.3           luanjia@taobao.com
    total=4
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    可以看到broken-clock-tinker模块已经正确被沙箱所加载

    如果修复代码用的是方法二 、到此为止 破损的时钟就已经被修复了,但是如果用的是方法一 修复clock#checkState()方法还需要一个触发操作

    ./sandbox.sh -p 64229 -d 'broken-clock-tinker/repairCheckState'
    
    除此之外 也可以用接口形式触发 参考:https://www.cnblogs.com/moonpool/p/14510443.html
    
    • 1
    • 2
    • 3

    3.6 问题修复
    过一会,模块生效完成,你就会发现原本一直抛异常的钟已经开始在刷新时间了,

    java.lang.IllegalStateException: STATE ERROR!
        at com.taobao.demo.Clock.checkState(Clock.java:16)
        at com.taobao.demo.Clock.report(Clock.java:34)
        at com.taobao.demo.Clock.loopReport(Clock.java:44)
        at com.taobao.demo.Clock.main(Clock.java:53)
    java.lang.IllegalStateException: STATE ERROR!
        at com.taobao.demo.Clock.checkState(Clock.java:16)
        at com.taobao.demo.Clock.report(Clock.java:34)
        at com.taobao.demo.Clock.loopReport(Clock.java:44)
        at com.taobao.demo.Clock.main(Clock.java:53)
    java.lang.IllegalStateException: STATE ERROR!
        at com.taobao.demo.Clock.checkState(Clock.java:16)
        at com.taobao.demo.Clock.report(Clock.java:34)
        at com.taobao.demo.Clock.loopReport(Clock.java:44)
        at com.taobao.demo.Clock.main(Clock.java:53)      
    2018-10-23 22:31:39
    2018-10-23 22:31:40
    2018-10-23 22:31:41
    2018-10-23 22:31:42
    2018-10-23 22:31:43
    2018-10-23 22:31:44
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    恢复被修复的check()方法
    当你卸载掉JVM-SANDBOX时候,你就会发现原本已经被修复好的钟,又开始继续报错了。原因是原来通过clock-tinker模块修复的checkState()方法随着沙箱的卸载又恢复成原来错误的代码流程。

    3.7、卸载沙箱

    ./sandbox.sh -p 64229 -S
    
    • 1

    三、总结

    可以通过这个工具最很多东西比如mock 网上有个很不错的mock开源项目
    https://github.com/chufusheng/imock

  • 相关阅读:
    LeetCode 94. 二叉树的中序遍历
    微信小程序传参的五种方式
    2022亚太数学杯数学建模竞赛B题(思路、程序......)
    【面试算法——动态规划 21】正则表达式匹配(hard)&& 交错字符串
    闲置的华为悦盒搭建海思NAS&Ubuntu系统(二)
    Pushmall推熵平台--对电商未来5年发展趋势分析
    vue 前端 用iframe实现单点登录
    centos 离线环境安装docker
    ChatGPT的ABAP能力如何?
    C#开发的OpenRA游戏之金钱系统(5)
  • 原文地址:https://blog.csdn.net/web18334137065/article/details/126619837