基于jvm-sandbox的mock项目:iMock 实现过程遇到的问题及解决
imock项目地址https://github.com/chufusheng/imock-web,作者很nice,中间沟通了很多次,感谢支持!!!
团队年度目标有一个搭建Mock平台任务,落到了我头上。
1、首先明确团队的需求
请求+响应由用户自己定义
启用,返回定义的响应结果
停用,返回自己服务的结果
2、调研分为两种方案
2.1 jvm-sandbox的mock服务,底层方法级别,功能满足,但操作相对复杂
2.2 Moco的mock服务,满足使用,简单易操作,团队想要平台级别,如果只是一个小工具的话有点勉强
3、方案实现过程
3.1 调研过程,开发基于阿里中间件 jvm-sandbox的mock服务,是Java方法级别的mock,操作就是监听指定方法,返回指定的mock内容。
3.2、阿里官方提供的demo「修复的钟」实现完成(网上很多不体现具体操作了)
目的:a.理解jvm-sandbox的mock的实现原理; b.给leader过程演示使用
缺点:被测试服务中【手动】接入mock;以demo作为基础可以做一个mock工具使用也可以支持。
Ø 手动安装sandbox;
Ø 手动查询被测试服务PID;
Ø 手动启动sandbox;
3.3imock的搭建
看到作者在GitHub上的贴图,感觉很适合做为一个平台项目使用,继续往下走。
下完后端和前端代码,编译前端代码各种配置冲突,看到后端有提供html页面,弃用了前端服务,精力有限啊。。
编译后端代码,解决各种冲突,开始本机装的mysql8以上,java8,后面还是换了mysql5(建议用mysql5),pom文件直接用作者的就可以。
第一步:数据初化 https://github.com/chufusheng/imock/tree/main/bin/sql
创建2张表,顺利完成。
第二步:启动mock服务管理后台 mock-web
mysql5+java8,配置好idea基本上不会有配置冲突,可以编译成功,服务也就起来了;
第三步:启动前端项目 imock-web(跳过)
第四步:安装mock-module(默认会安装jvm-sandbox)
本地安装 到项目下的bin目录执行 install-local.sh;「提示⚠️:GitHub上作者提供的文件中命令需要修改。作者直接邮件发了我一份,完美解决」
远程安装到目标应用curl -s https://kunchu.oss-cn-beijing.aliyuncs.com/install-troublemaker.sh |sh「项目还没部署到服务器,暂时没用到」
第五步:配置目标应用
通过配置文件配置 进入根目录下的隐藏目录 ~/.sandbox-module/cfg 修改mock.properties「提示⚠️:mock.host=http://127.0.0.1:8003,这个是mock服务的地址」
启动被测应用时带上 java 环境变量「上面已经配置了app.name 、app.env,这里不用带」
第六步:启动
ü 通过jps查看 被测应用的java 进程 比如 1234(启动被测服务的终端上,会直接显示进程号,直接复制使用)
ü 到根目录 ~/sandbox/bin 执行 ./sandbox.sh -p 1234
ü 被测试服务与mock服务建立心跳(这里之前一直没有获取到被测服务的应用,排查了好几遍debug日志,最后和作者沟通后,发现是配置的mock.host是被测服务的😂,应该是mock服务的)
排查过程:
//跟踪建立心跳的过程,发现是jvm-sandbox的底层代码实现的;
//附上阿里云上的源码解析https://developer.aliyun.com/article/716768
class AppTask 每小时检查1次Status; interface ModuleInfoService 查询Status,getAppHeart class MockResult<T> class ResultHelper class ModuleConfigServiceImpl,stopAndOpen 操作开关 class ModuleInfo implements java.io.Serializable :在线模块信息 //通过jvm.sandbox获取被测试应用信息,建立心跳 class HeartbeatHandler interface ConfigInfo(jvm.sandbox) class MockModule interface ModuleEventWatcher(jvm.sandbox) interface LoadedClassDataSource(jvm.sandbox)
过程排查的问题:
问题1:建立心跳后,点击「冻结」或「更新配置」按钮,接口返回:
success: false
message:"Invoke failed, status code is not 200
debug日志:Column ‘createTime’ cannot be null
报错原因是:
我用的是Mysql8,explicit_defaults_for_timestamp 系统变量决定MySQL服务端对timestamp列中的默认值和NULL值的不同处理方法。
此变量自MySQL 5.6.6 版本引入,分为全局级别和会话级别,可动态更新,默认值为OFF。
在8.0之中默认值改为了on。
解决方法:最好还是安装mysql5吧。
debug过程中,还有其他异常报出来,都看了一遍,不影响运行,可以忽略:
问题:org.springframework.boot:type=Admin,name=SpringApplication(log-debug引起)
问题:java.lang.reflect.InaccessibleObjectException
问题:no tcnative-1 in java.library.path, no libtcnative-1 in java.library.path(只是优化,不是error)
问题:Use of DefaultSchemaNameResolver requires Dialect to provide the proper SQL statement/command but provided Dialect(框架内部抛出的异常)
问题:Unable to create a Configuration, because no Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.
问题:Http11Processor : Error parsing HTTP request header(因为tomcat自8.5.x系列对于非保留字字符(json格式的请求参数)必须做转义操作)
至此,可以建立稳定心跳,顺利获取被测应用的信息了。。
后面还有就是配置后,请求接口时没有返回mock的响应结果,正在和项目作者沟通,忽听闻我leader被撤了😂,,,人生无常啊