记:针对框架级别的bug如何高效排查及如何修复

发布时间 2023-07-21 11:35:04作者: 贝克田庄

笔记最近从事公司混沌工程平台的搭建及研发工作。在平台研发及用户使用过程中发现了大量的框架级别的bug。并修复大量bug,并对插件做了扩展。

平台是基于阿里开源的chaosblade框架搭建而成。我选取了一个典型的故障排查过程作为故障排查思路总结

一:基于jdk11版本的jvm下的脚本故障注入失败

在业务部门做异常测试的过程中,对于一些复杂的场景测试下,很难针对方法源码级别的故障注入异常模拟,但是这种场景又大量需要。这时候我们就需要使用到java脚本自定义脚本故障注入。但chaosblade1.7.2以下的版本中,java脚本自定义故障存在bug,脚本注入失败。

1. 排查第一步:看日志

这时候我们需要查看多个位置的日志,优先到注入目标容器查看第一现场日志:/root/logs/chaosblade/chaosblade.log

2. 排查第二步:重现bug

从日志中可以看到,脚本编译失败。但是这已经是所有能看到的错误日志了。如果看到这里。我们只知道脚本编译失败了,没有任何其他信息了,如果经验不够,很容易造成误判,觉得这是脚本写的有问题导致了编译异常。笔者也犯了同样的错误。和也业务方做了大量沟通,同时我花了很多时间去重现 这个问题无果。在观察用户服务配置发现用户使用的jdk版本和笔者使用的jdk版本有差别。用户使用的是jdk11,笔者使用到的jdk8。为此,我通过将环境和用户保持一致重现了这个bug。

3. 排查第三步:深究原因

通过第二步的操作,我们知道出现的原因是用户使用的jdk版本导致出现了这个bug。但是jdk11版本下为啥会出现这个问题,就需要我们进一步深究了。这时候我们查看原生打出的日志,似乎又走进了死胡同。因为日志给出的信息实在有限。但是也足够进一步排查故障了。我们通过日志堆栈,找到框架报错的代码。这时候报错的位置定位到了JavaCodeScriptEngine类中compileClass方法。

从日志报错信息看,代码进入了else逻辑,这时候也能看出,确实是代码编译报错。但是除了日志中打印的错误,并没有看到程序本身出现了什么错误。无法继续排查。

4. 排查第四步:查看官方github issues

这时候我们没有思路的情况下,不应该死磕,需要另辟蹊径查看别人是否也和我们遇到了同样的问题。但是笔者针对这个问题在官网查看一圈下来,也没有遇到相同的问题。事情再一次走进死胡同。

5. 排查第五步:添加自定义日志,辅助排查

 我们看 compileClass方法的源码的时候,看到了使用到了jdk的编译工具javacompiler类,根据我对该类的了解,该方法使用的时候,可以out更多的信息,但是框架开发者对该参数采取了null设置。所以这时候我们需要手动添加打印信息,如下:

 最后一番折腾下我们终于看到了隐藏在编译报错下的真实内容了,找不到java.lang

6. 排查第六步:根据日志针对性定位到问题代码

从日志我们可以看到明显的报错,找不到java.lang,我们都知道java属于编译运行的。在之前需要对依赖类进行类加载操作。同时我需要明白chaosblade底层运行机制,这个读者可自行研究。

这时候我们需要找到框架加载依赖类库的代码

可以看到这段代码是对java类文件内存加载的代码,我们进入源码仔细阅读源码

从上图这可以看到,重现了list方法。在这里做了处理。至此我们找到了定位到了加载类库这里我们遗漏了java.lang包。同时为了验证,笔者当时对加载的逻辑也注入了日志打印。并在过程中,终于找到了,包没有走到加载的逻辑,导致没有被加载进去。(因为现场没有保留,笔者这里不做贴图)

7. 排查第七步:找出问题根因

从以上我们已经知道了,是框架在类库的时候漏掉了java.lang包,所以这时候我思考,为啥jdk8以下情况下正常运行,jdk11出现了java.lang加载被漏掉。这时候我们需要弄清楚jdk8和jdk11在依赖库location做了什么变化,我们需要查看资料弄清楚的问题:

从官方文件中我无法找到jdk8和jdk11在类库路径上对比,最后找到微软官方一篇文章从java8过渡到java11中找到了重点。https://learn.microsoft.com/en-us/java/openjdk/transition-from-java-8-to-java-11

 从这句话清楚告诉了我们,在迁移到jdk11过程中需要注意将类路径迁移到模块化路径上。这时候再看官方资料就能更清楚我们需要查找什么内容。java9之后的版本中引入SYSTEM_MODULE,所以该段代码会在jdk9之后无法获取对应模块化包,所以需要进行相关的兼容(相关修复代码已经提交给chaosblade团队并已经更新到1.7.2版本中) https://github.com/chaosblade-io/chaosblade-exec-jvm/pull/301