背景与导读

对 jvm-sandbox-repeater 做了有一段时间的学习和调研,看到目前 repeater 相关的文章比较少,所以将自己这段时间了解到的内容整理出来,分享给大家。

学习笔记分成入门使用篇和原理说明篇两个篇章。
入门使用篇主要是基于官方文档和 testerhome 其他的操作文档,对 repeater 的使用上的操作细节和配置做了补充说明,建议大家先按照官方的文档使用过了之后,再看这些文档,能够更好地理解文档内容。
原理说明篇则是主要围绕录制流程和回放流程,进行相关的源码分析说明,个人道行尚浅,若分析有错漏,欢迎大家指正补充

笔记中的每一个篇都有建立在此前篇章的基础上,建议按照顺序阅读。
在这里记录下系列文章地址:
[jvm-sandbox-repeater 学习笔记][入门使用篇] 1 安装与启动(本文)
[jvm-sandbox-repeater 学习笔记][入门使用篇] 2 配置说明
[jvm-sandbox-repeater 学习笔记][入门使用篇] 3 现有接口说明
[jvm-sandbox-repeater 学习笔记][入门使用篇] 4 录制、回放与调试

1.1 环境准备

安装包括 repeater 安装、repeater-console 安装

目前安装和使用,需要 mac 或者 linux 系统下进行,如果在 windows 下进行可能会遇到安装路径出错导致安装失败或者运行失败的情况。

PS:如果只是想简单运行,可以直接使用官方版本,参考官方用户手册,以standalone模式把玩。

1.2 repeater-console 安装与启动

当我们真正进行使用的时候,一般采取非standalone模式,需要 repeater-console 结合使用。

PS:repeater 与 repeater-console 之间的协作关系简单来说:repeater 负责执行录制任务和回放任务,而 repeate-console 则是负责将录制记录和回放结果保存,并提供接口给用户触发回放任务。

1.2.1 克隆源码

# 克隆代码到本地
git clone https://github.com/alibaba/jvm-sandbox-repeater.git

1.2.2 启动 repeater-console

方法有二:

  1. 【本地试用强烈推荐】idea 右键运行启动:jvm-sandbox-repeater/repeater-console/repeater-console-start/src/main/java/com/alibaba/repeater/console/start/Application.java
  2. 打成 jar 包运行,项目根目录路径下执行以下命令。
mvn clean install -Dmaven.test.skip=true && java -jar repeater-console/repeater-console-start/target/repeater-console.jar

1.3 repeater 安装

安装时必须保证安装用户与被录制应用启动的用户一致。

可以直接执行官方文档中的安装脚本,也可使用本地源码安装。

1.3.1 本地源码安装

  1. 克隆源码到本地
# 克隆代码到本地
git clone https://github.com/alibaba/jvm-sandbox-repeater.git
  1. 修改 repeater 配置,配置路径:jvm-sandbox-repeater/bin/repeater.properties。如下,主要修改内容为将所有 url 的主机地址改为 127.0.0.1 以及本地 repeater-console 的端口,repeat.standalone.mode改为false

repeat.standalone.mode控制 repeater 是否以 standalone 模式启动,我们要与 repeater-console 结合使用,所以配置为false。其他 url 都是与 repeater-console 交互的 url,所以需要将 host 改为本地启动的 repeater-console 的地址。

# 录制消息投递地址
broadcaster.record.url=http://127.0.0.1:8001/facade/api/record/save

# 回放结果投递地址
broadcaster.repeat.url=http://127.0.0.1:8001/facade/api/repeat/save

# 回放消息取数据地址
repeat.record.url=http://127.0.0.1:8001/facade/api/record/%s/%s

# 配置文件拉取地址
repeat.config.url=http://127.0.0.1:8001/facade/api/config/%s/%s

# 是否开启脱机工作模式
repeat.standalone.mode=false
  1. 到代码的 bin 文件夹下执行 install-local.sh 脚本。执行完成即可。
# 到代码的bin文件夹下执行 install-local.sh 脚本
cd jvm-sandbox-repeater/bin
sh install-local.sh

1.4 repeater 启动与关闭

repeater 的启动方法有两种。attach 模式和 agent 模式。

启动 repeater 之后就会从 repeater-console 拉取配置,根据配置对请求进行筛选,开始录制。并且可以接收回放请求,随时进行请求。

1.4.1 attach 模式启动与关闭

切换至被录制应用启动用户,执行以下启动命令。注意 repeater 启动端口需要选取一个没有被占用的端口。

attach 模式下,录制应用名和录制环境这两个参数都会被默认为unknown

# 启动命令
~/sandbox/bin/sandbox.sh -p ${被录制应用进程号} -P ${repeater启动端口}
# 关闭命令
~/sandbox/bin/sandbox.sh -S ${被录制应用进程号}

启动成功/关闭成功的结果:

# 启动成功
elesgongdeMac-mini:~ elesgong$ sh ~/sandbox/bin/sandbox.sh -p 6170 -P 8821
                    NAMESPACE : default
                      VERSION : 1.2.1
                         MODE : ATTACH
                  SERVER_ADDR : account.jetbrains.com
                  SERVER_PORT : 8821
               UNSAFE_SUPPORT : ENABLE
                 SANDBOX_HOME : /Users/elesgong/sandbox/bin/..
            SYSTEM_MODULE_LIB : /Users/elesgong/sandbox/bin/../module
              USER_MODULE_LIB : /Users/elesgong/sandbox/sandbox-module;~/.sandbox-module;
          SYSTEM_PROVIDER_LIB : /Users/elesgong/sandbox/bin/../provider
           EVENT_POOL_SUPPORT : DISABLE
# 关闭成功
elesgongdeMac-mini:~ gongying$ sh ~/sandbox/bin/sandbox.sh -p 6170 -S

jvm-sandbox[default] shutdown finished.

1.4.2 agent 模式下启动与关闭

需要重启被录制的应用。在 java 启动参数中加入对应的参数,如下。

agent 模式下的启停都跟随应用,配置好参数后,应用启动则启动,应用停止则停止。

java 
-javaagent:${HOME}/sandbox/lib/sandbox-agent.jar=server.port=${repeater启动端口}\;server.ip=0.0.0.0 \
-Dapp.name=${录制应用名} \
-Dapp.env=${录制环境} \
-jar application.jar

启动成功检查方法:

  1. 应用正常启动,无报错

  2. 看日志,日志路径~/logs/sandbox/repeater/repeater.log。

需要关注的日志内容主要是是以下几种:

PS:其中会夹杂很多以Register bean:name=的日志,这些日志说明了被 repeater 记录下来的运行在应用 jvm 中的实例,会在 java 回放的时候用到。但是与启动 repeater 关系不大,在启动阶段可忽略。

2019-10-08 18:44:51 INFO  initializing logback success. file=/Users/elesgong/.sandbox-module/cfg/repeater-logback.xml;
2019-10-08 18:44:51 INFO  module on loaded,id=repeater,version=1.0.0,mode=AGENT
2019-10-08 18:44:51 INFO  agent launch mode,use Spring Instantiate Advice to register bean.
2019-10-08 18:44:51 INFO  onActive
2019-10-08 18:44:53 INFO  pull repeater config success,config=com.alibaba.jvm.sandbox.repeater.plugin.domain.RepeaterConfig@56996122
2019-10-08 18:44:53 INFO  http plugin required servlet-api class router,waiting for class loading
2019-10-08 18:44:54 INFO  http plugin required servlet-api class router,waiting for class loading
2019-10-08 18:44:55 INFO  enable plugin mybatis success
2019-10-08 18:44:56 INFO  add watcher success,type=mybatis,watcherId=1003
2019-10-08 18:44:56 INFO  enable plugin redis success
2019-10-08 18:44:56 INFO  add watcher success,type=redis,watcherId=1005
2019-10-08 18:44:57 INFO  add watcher success,type=redis,watcherId=1007
2019-10-08 18:44:57 INFO  enable plugin http success
2019-10-08 18:44:57 INFO  add watcher success,type=http,watcherId=1009
2019-10-08 18:44:57 INFO  enable plugin java-entrance success
2019-10-08 18:44:57 INFO  watch plugin occurred error
com.alibaba.jvm.sandbox.repeater.plugin.exception.PluginLifeCycleException: enhance models is empty, plugin type is java-entrance
    at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.AbstractInvokePluginAdapter.watchIfNecessary(AbstractInvokePluginAdapter.java:122)
    at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.AbstractInvokePluginAdapter.watch(AbstractInvokePluginAdapter.java:65)
    at com.alibaba.jvm.sandbox.repeater.module.RepeaterModule.initialize(RepeaterModule.java:187)
    at com.alibaba.jvm.sandbox.repeater.module.RepeaterModule.access$500(RepeaterModule.java:61)
    at com.alibaba.jvm.sandbox.repeater.module.RepeaterModule$1.run(RepeaterModule.java:133)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
2019-10-08 18:44:57 INFO  enable plugin java-subInvoke success
2019-10-08 18:44:58 INFO  add watcher success,type=java,watcherId=1011
2019-10-08 18:44:58 INFO  add watcher success,type=java,watcherId=1013
2019-10-08 18:44:59 INFO  add watcher success,type=java,watcherId=1019
2019-10-08 18:44:59 INFO  add watcher success,type=java,watcherId=1021
2019-10-08 18:44:59 INFO  add watcher success,type=java,watcherId=1023
2019-10-08 18:44:59 INFO  add watcher success,type=java,watcherId=1025
2019-10-08 18:45:00 INFO  add watcher success,type=java,watcherId=1027
2019-10-08 18:45:00 INFO  add watcher success,type=java,watcherId=1029
2019-10-08 18:45:00 INFO  add watcher success,type=java,watcherId=1031
2019-10-08 18:45:00 INFO  add watcher success,type=java,watcherId=1033
2019-10-08 18:45:00 INFO  add watcher success,type=java,watcherId=1035
2019-10-08 18:45:01 INFO  add watcher success,type=java,watcherId=1041
2019-10-08 18:45:01 INFO  register event bus success in repeat-register


出现部分插件加载失败的情况,大多数是由于配置错误,如下错误日志是由于在pluginIdentities中配置了java-entrance插件,却在javaEntranceBehaviors中配置了空数组导致。

错误配置:

{
  "useTtl": true,
  "degrade": false,
  "exceptionThreshold": 1000,
  "sampleRate": 10000,
  "pluginsPath": null,
  "httpEntrancePatterns": [
    "^/api/city/.*$"
  ],
  "javaEntranceBehaviors": [
  ],

  "javaSubInvokeBehaviors": [
    {
      "classPattern": "com.test.commons.util.DateUtils",
      "methodPatterns": [
        "getNowDateTime",
        "getNowDate"

      ],
      "includeSubClasses": false
    },
    ...
    ...
  ],
  "pluginIdentities": [
    "http",
    "java-entrance",
    "java-subInvoke",
    "mybatis",
    "redis"
  ],
  "repeatIdentities": [
    "http",
    "java"
  ]
}


错误日志:

2019-10-08 18:44:57 INFO  watch plugin occurred error
com.alibaba.jvm.sandbox.repeater.plugin.exception.PluginLifeCycleException: enhance models is empty, plugin type is java-entrance
    at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.AbstractInvokePluginAdapter.watchIfNecessary(AbstractInvokePluginAdapter.java:122)
    at com.alibaba.jvm.sandbox.repeater.plugin.core.impl.AbstractInvokePluginAdapter.watch(AbstractInvokePluginAdapter.java:65)
    at com.alibaba.jvm.sandbox.repeater.module.RepeaterModule.initialize(RepeaterModule.java:187)
    at com.alibaba.jvm.sandbox.repeater.module.RepeaterModule.access$500(RepeaterModule.java:61)
    at com.alibaba.jvm.sandbox.repeater.module.RepeaterModule$1.run(RepeaterModule.java:133)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

1.4.3 attach 和 agent 启动模式对比

模式 优点 不足
attach 1. 不需要启停应用,即插即用,随时停止
2. 更新配置不需要重启应用
1. 进行 java 回放的时候可能由于无法获取到对应实例而回放失败
2. 如果需要对 repeater 进行 debug,需要将 repeater 代码嵌入到被录制应用的代码中,不方便 debug
3. 不可进行录制应用名和录制环境的配置,会被默认标记为 unknown
agent 1. 进行 java 回放的时候能够获取到对应实例能够正常回放
2. 启动应用时开启调试,即可远程调试 repeater
3. 支持配置录制应用名以及录制环境,方便在录制记录中进行区分
1. 启动/停止都需要重启应用
2. 更新配置也需要重启应用


↙↙↙阅读原文可查看相关链接,并与作者交流