开发者

Jvm sandbox mock机制的实践过程

目录
  • 一、背景
  • 二、定义一个损坏的钟
    • 1、 Springboot工程中创建一个Clock类
    • 2、 添加一个Controller类
    • 3、 部署该Springboot项目到linux服务器上运行
  • 三、修复这个损坏的钟
    • 1、 编写一个模块修复损坏的钟
    • 2、 下载并安装jvm-sandbox
    • 3、 将修复的jar包复制到sandbox-module目录下
    • 4、 启动sandbox
    • 5、 修复clock#checkState()方法
    • 6、 恢复被修复的check()方法
  • 总结

    一、背景

    Jvm sandbox沙箱机制,是一种实现不重启、无侵入改变目标应用返回值的面向切面编程解决方案。测试方面来说,对于RPC接口、HTTP接口都适用。

    如果需要开发一个比较全面的mock平台,不仅仅是简单的http接口mock,则可以考虑该方案。

    本次主要介绍使用官网的案例,进行实践测试效果,后续会介绍如何利用Jvm sandbox搭建Mock平台。

    二、定义一个损坏的钟

    下面直接以Linux服务器上的实操举例,MAC同理。

    我们先创建一个Springboot工程,工程中定义一个Controller类定义URL入口,调用Clock类,Clock类为官网案例:一个损坏了的钟。

    1、 Springboot工程中创建一个Clock类

    代码如下:

    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();
        }
    
    }

    本地运行之后,会看到目前一直在报异常:

    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)

    2、 添加一个Controller类

    指向运行Clock类中的loopReport方法:

    import com.taobao.demo.service.Clock;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.编程web.bind.annotation.RestController;
    
    @Slf4j
    @RestController
    @RequestMapping("clock")
    public class ClockController {
    
        @Autowired
        Clock clock;
    
        @RequestMapping("/start")
        public void start() throws InterruptedException {
            log.info("start clock");
            clock.loopReport();
        }
    }

    3、 部署该S编程客栈pringboot项目到linux服务器上运行

    访问定义好的接口:http://服务器IP地址:8080/clock/start, 会看到目前一直在报错:

    Jvm sandbox mock机制的实践过程

    三、修复这个损坏的钟

    1、 编写一个模块修复损坏的钟

    创建一个maven工程:clock-tinker, pom.XML添加“sandbox-module-starter” maven依赖:

    <parent>
        <groupId>com.alibaba.jvm.sandbox</groupId>
        <artifactId>sandbox-module-starter</artifactId>
        <version>1www.devze.com.2.0</version>
    </parent> 

    编写“BrokenClockTinkerModule ”类,修复损坏的钟代码:

    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.EventWatchBujsilder;
    import com.alibaba.jvm.sandbox.api.resource.ModuleEventWatcher;
    import org.kohsuke.MetaInfServices;
    
    import javax.annotation.Resource;
    
    @MetaInfServices(Module.class)
    @Information(id = "broken-clock-tinker")
    public class BrokenClockTinkerModule implements Module {
    
        @Resource
        private ModuleEventWatcher moduleEventWatcher;
    
        @Command("repairCheckState")
        public void repairCheckState() {php
    
            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);
                        }
                    });
        }
    }

    编译部署clock-tinker工程:

    mvn clean package

    项目工程的target目录下会生成“clock-tinker-1.0-SNAPSHOT-jar-with-dependencies.jar” 包:

    Jvm sandbox mock机制的实践过程

    2、 下载并安装jvm-sandbox

    下载地址:https://ompc.oss.aliyuncs.com/jvm-sandbox/release/sandbox-stable-bin.zip

    使用命令wget下载后,解压:

    unzip sandbox-stable-bin.zipcd sandbox

    目录结构如下:

    Jvm sandbox mock机制的实践过程

    3、 将修复的jar包复制到sandbox-module目录下

    cp target/clock-tinker-1.0-SNAPSHOT-jar-with-dependencies.jar ~/.sandbox-module/

    4、 启动sandbox

    使用命令:ps -ef | grep java , 查到服务器上启动的被损坏的钟clock的java 进程号,比如进程号是:1。

    进入到解压后的sandbox的bin目录下,使用以下命令启动sandbox:

    ./sandbox.sh -p 1

    Jvm sandbox mock机制的实践过程

    使用以下命令查看模块:

    ./sandbox.sh -p 1 -l

    Jvm sandbox mock机制的实践过程

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

    5、 修复clock#checkState()方法

    接下来就是重头戏,如何在不影响目标应用的情况下,无声无息的修复这个故障!

    触发broken-clock-tinker模块的repairCheckState(),让修复逻辑生效。

    执行命令:触发BrokenClockTinkerModule#repairCheckState()方法执行

    ./sandbox.sh -p 1 -d 'broken-clock-tinker/repairCheckState'

    Jvm sandbox mock机制的实践过程

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

    Jvm sandbox mock机制的实践过程

    6、 恢复被修复的check()方法

    停止sandbox的命令:

    ./sandbox.sh -p 64229 -S

    Jvm sandbox mock机制的实践过程

    会看到提示信息:

    jvm-sandbox[default] shutdown finished.

    你就会发现原本已经被修复好的钟,又开始继续报错了。

    原因是原来通过clock-tinker模块修复的checkState()方法随着沙箱的卸载又恢复成原来错误的代码流程:

    Jvm sandbox mock机制的实践过程

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜