对 jvm-sandbox-repeater 做了有一段时间的学习和调研,看到目前 repeater 相关的文章比较少,所以将自己这段时间了解到的内容整理出来,分享给大家。
学习笔记分成入门使用篇和原理说明篇两个篇章。
入门使用篇主要是基于官方文档和 testerhome 其他的操作文档,对 repeater 的使用上的操作细节和配置做了补充说明,建议大家先按照官方的文档使用过了之后,再看这些文档,能够更好地理解文档内容。
原理说明篇则是主要围绕录制流程和回放流程,进行相关的源码分析说明,个人道行尚浅,若分析有错漏,欢迎大家指正补充。
笔记中的每一个篇都有建立在此前篇章的基础上,建议按照顺序阅读。
在这里记录下系列文章地址:
[jvm-sandbox-repeater 学习笔记][入门使用篇] 1 安装与启动(本文)
[jvm-sandbox-repeater 学习笔记][入门使用篇] 2 配置说明
[jvm-sandbox-repeater 学习笔记][入门使用篇] 3 现有接口说明
[jvm-sandbox-repeater 学习笔记][入门使用篇] 4 录制、回放与调试
安装包括 repeater 安装、repeater-console 安装
目前安装和使用,需要 mac 或者 linux 系统下进行,如果在 windows 下进行可能会遇到安装路径出错导致安装失败或者运行失败的情况。
PS:如果只是想简单运行,可以直接使用官方版本,参考官方用户手册,以standalone
模式把玩。
当我们真正进行使用的时候,一般采取非standalone
模式,需要 repeater-console 结合使用。
PS:repeater 与 repeater-console 之间的协作关系简单来说:repeater 负责执行录制任务和回放任务,而 repeate-console 则是负责将录制记录和回放结果保存,并提供接口给用户触发回放任务。
# 克隆代码到本地
git clone https://github.com/alibaba/jvm-sandbox-repeater.git
方法有二:
mvn clean install -Dmaven.test.skip=true && java -jar repeater-console/repeater-console-start/target/repeater-console.jar
安装时必须保证安装用户与被录制应用启动的用户一致。
可以直接执行官方文档中的安装脚本,也可使用本地源码安装。
# 克隆代码到本地
git clone https://github.com/alibaba/jvm-sandbox-repeater.git
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
# 到代码的bin文件夹下执行 install-local.sh 脚本
cd jvm-sandbox-repeater/bin
sh install-local.sh
repeater 的启动方法有两种。attach 模式和 agent 模式。
启动 repeater 之后就会从 repeater-console 拉取配置,根据配置对请求进行筛选,开始录制。并且可以接收回放请求,随时进行请求。
切换至被录制应用启动用户,执行以下启动命令。注意 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.
需要重启被录制的应用。在 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
启动成功检查方法:
应用正常启动,无报错
看日志,日志路径~/logs/sandbox/repeater/repeater.log。
需要关注的日志内容主要是是以下几种:
enable plugin
开头的,查看插件挂载情况register event bus success in repeat-register
,说明插件加载完成,模块加载完成,可以开始录制和回放的行为。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)
模式 | 优点 | 不足 |
---|---|---|
attach | 1. 不需要启停应用,即插即用,随时停止 2. 更新配置不需要重启应用 |
1. 进行 java 回放的时候可能由于无法获取到对应实例而回放失败 2. 如果需要对 repeater 进行 debug,需要将 repeater 代码嵌入到被录制应用的代码中,不方便 debug 3. 不可进行录制应用名和录制环境的配置,会被默认标记为 unknown |
agent | 1. 进行 java 回放的时候能够获取到对应实例能够正常回放 2. 启动应用时开启调试,即可远程调试 repeater 3. 支持配置录制应用名以及录制环境,方便在录制记录中进行区分 |
1. 启动/停止都需要重启应用 2. 更新配置也需要重启应用 |