原教程地址查看 【GITHUB教程地址】
本帖只记录遇到的错误以及对应的解决办法。
数据库字段报错
问题描述如下
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'moduleconf0_.app_name' in 'field list'
这是因为Repeater代码必须使用数据库进行存储操作,而新入门的情况下,本地应该都没有搭建好数据库,所以必然会报这个错误。
而类似的问题很多,如果手动一个个去试验的找出所有数据库表和字段明显不靠谱,耗时耗力不说,还非常容易漏掉字段或者字段类型出现问题,导致最终无法下手。
而一般情况下,应该都会有对应的.sql文件去兜底这件事。所以找到.sql文件应该能解决这个问题。
往下查看报错信息,会发现如下内容
at com.alibaba.repeater.console.dal.dao.ModuleConfigDao.query(ModuleConfigDao.java:48) ~[repeater-console-dal-1.0.0-SNAPSHOT.jar!/:na]
at com.alibaba.repeater.console.service.impl.ModuleConfigServiceImpl.query(ModuleConfigServiceImpl.java:69) ~[repeater-console-service-1.0.0-SNAPSHOT.jar!/:na]
at com.alibaba.repeater.console.start.controller.api.ConfigFacadeApi.getConfig(ConfigFacadeApi.java:33) ~[classes!/:na]
会发现和JVM-SandBox-Repeater有关的报错只有这三行,逐一查找jar包反编译后的文件,会在 jvm-sandbox-repeater/repeater-console/repeater-console-dal/target/classes/database.sql
这个文件中找到所有的数据库表和字段内容。
直接使用这个文件创建数据库,即可解决这个问题。
空指针问题
问题描述如下
java.lang.NullPointerException: null
java中不要太常见的问题。这个问题主要出现在以下代码的最后一行
@RequestMapping("/config/{appName}/{env}")
public RepeaterResult<RepeaterConfig> getConfig(@PathVariable("appName") String appName,
@PathVariable("env") String env) {
ModuleConfigParams params = new ModuleConfigParams();
params.setAppName(appName);
params.setEnvironment(env);
RepeaterResult<ModuleConfigBO> result = moduleConfigService.query(params);
return RepeaterResult.builder().success(result.isSuccess()).message(result.getMessage()).data(result.getData().getConfigModel()).build();
}
getConfig
方法在返回数据时,会从数据库获取对应 appName
和 env
的数据,而全新环境下,数据库没有任何内容,所以只能获得一个空值,最终导致空指针错误。
通过名字可以比较明显的看出来,只需要往 module_config
表中插入数据,应该可以解决这个问题。
最后把原生配置文件中的内容作为config,插入一条新的配置数据导数据库,具体如下
insert into module_config (gmt_create, gmt_modified, app_name, environment, config) values ('2020-11-23 08:04', '2020-11-23 08:04', 'repeater', 'daily', '{ "useTtl" : true, "degrade" : false, "exceptionThreshold" : 1000, "sampleRate" : 10000, "pluginsPath" : null, "httpEntrancePatterns" : [ "^/regress/.*$" ], "javaEntranceBehaviors" : [ { "classPattern" : "com.alibaba.repeater.console.service.impl.RegressServiceImpl", "methodPatterns" : [ "getRegress" ], "includeSubClasses" : false } ], "javaSubInvokeBehaviors" : [ { "classPattern" : "com.alibaba.repeater.console.service.impl.RegressServiceImpl", "methodPatterns" : [ "getRegressInner", "findPartner", "slogan" ], "includeSubClasses" : false } ], "pluginIdentities" : [ "http", "java-entrance", "java-subInvoke" ], "repeatIdentities" : [ "java", "http" ] }');
这样,上面的代码就可以正常的从数据库获取到一条数据。
此时再执行如下命令,就可以正确的进行回放
# 重新编译代码
mvn clean install -Dmaven.test.skip=true
# 启动
./bin/bootstrap.sh
# 录制
curl -s 'http://127.0.0.1:8001/regress/slogan?Repeat-TraceId=127000000001156034386424510000ed'
# 回放
curl -s 'http://127.0.0.1:8001/regress/slogan?Repeat-TraceId-X=127000000001156034386424510000ed'
如无意外,回放时会返回 <h1 align="center" style="color:red;margin-top:300px">JAVA是世界上最好的语言!</h1>
录制自己的应用时,没能捕获到数据
解决完上面两个问题后,教程的第一步,standalone 模式的录制和回放已经无法再满足我了,于是继续向下看,准备录制自己的应用流量。
修改完 repeater-config.json 文件,只保留了 http 请求的流量,将正则匹配中的 regress 也改为自己的接口路径的内容后,发现 repeater.log 中依然只有冷冰冰的启动成功的提示,没有更多的日志。
一番折腾下,终于想起来修改日志等级,打开 ~/.sandbox-module/cfg/repeater-logback.xml
,将日志等级从 info 调整为 debug,最终如下所示
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="10000">
<appender name="REPEATER-FILE-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${user.home}/logs/sandbox/repeater/repeater.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${user.home}/logs/sandbox/repeater/repeater.log.%d{yyyy-MM-dd}</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
# 修改这里
<root level="debug">
<appender-ref ref="REPEATER-FILE-APPENDER"/>
</root>
</configuration>
再次编译启动 repeater-console,重启 repeater 之后,发现多了一堆信息,其中有一条为 current uri {你的请求路径} can't match any httpEntrancePatterns, ignore this request
。
所以确认是正则匹配失败导致的,全局搜索一下这句话,很方便能找到如下的代码
# HttpStandaloneListener.java
private boolean matchRequestURI(List<String> patterns, String requestURI) {
if (CollectionUtils.isEmpty(patterns)) {
return false;
}
for (String pattern : patterns) {
if (requestURI.matches(pattern)) {
return true;
}
}
return false;
}
如果对于正则不是很有信心,可以将代码拷贝出去一个个的试,得到正确的匹配规则集。
将试验后返回true的正则更新到配置文件后,再次编译启动 repeater-console,重启 repeater ,发送请求后,会在数据库中正确查看到新录制到的流量信息。
至此,在服务器数据库环境下录制流量的任务就算完成了。
总结
总的来说 standalone 模式下的流程和非 standalone 模式的流程还是非常相似,都是将录制到的数据保存到数据库。
在调试通单机模式后,再去录制自己的应用流量时,会简单很多,不过我还是在正则这块卡了比较久,一个是对于Java正则的不熟悉,另一个可能也是惯性思维,让我认为只要把 regress 这个单词替换了应该其他的也行的通。
虽然经过一番折腾算是在服务器将流量录制好了,但是就教程来说,依然槽点满满,是一份照本宣科后无法入门的教程,而且一年多没更新了,劝退能力MAX,我一度怀疑是代码更新了比较多,但是教程没有及时更新导致我卡了不少地方。