线上应用诊断与调试利器——Arthas( 二 )


线上应用诊断与调试利器——Arthas文章插图
显示所有被记录的调用列表
tt -l
线上应用诊断与调试利器——Arthas文章插图
重做一次调用 。 tt 命令由于保存了当时调用的所有现场信息 , 所以我们可以自己主动对一个 INDEX 编号的时间片自主发起一次调用 , 从而解放你的沟通成本 。 此时你需要 -p 参数 。 通过 --replay-times 指定 调用次数 , 通过 --replay-interval 指定多次调用间隔(单位ms, 默认1000ms)
tt -i 1001 -p --replay-times 3 --replay-interval 3000
线上应用诊断与调试利器——Arthas文章插图
jad
jad 命令将 JVM 中实际运行的 class 的 byte code 反编译成 java 代码 , 便于你理解业务逻辑;反编译出来的源码是带语法高亮的 , 阅读更方便 。 当我们看到某个方法的调用时长明显过长 , 或者时空隧道中某方法抛出异常 , 这个时候就可以直接反编译相关的方法 , 看看是否能找出原因 。
线上应用诊断与调试利器——Arthas文章插图
其他
除了以上很常用的命令以外 , arthas还有很多实用命令 , 大家可以参考官方文档来使用
另外 , 每一个命令都支持-help参数 , 可以查看该命令的说明、参数 , 甚至包括了使用例子 , 可以说是非常贴心了
线上应用诊断与调试利器——Arthas文章插图
案例
案例1
我们准备了一个简单的springboot应用 , 应用内有一个Controller , 返回一个字符串 , 代码如下:
@RestControllerpublic class DemoController {??@GetMapping(value = "http://kandian.youth.cn/getDemo")public String getDemo(){return "demo 1";}}启动程序 , 访问刚刚准备好的controller得到了下面的结果
线上应用诊断与调试利器——Arthas文章插图
接下来我们要尝试在没有源码的情况下修改demo controller的返回值 , 并在不重启应用的情况下,使我们修改的返回值生效 。
首先启动arthas并织入到刚才的demo , 然后反编译DemoController到临时文件夹 。
jad --source-only com.example.arthas.DemoController >/tmp/DemoController.java接下来我们用vim修改反编译出来的代码
线上应用诊断与调试利器——Arthas文章插图
查询加载原有DemoController类的ClassLoader
sc -d com.example.arthas.DemoController重新编译修改后的类
mc -c 685f4c2e /tmp/DemoController.java重新加载修改后的类
redefine -c 685f4c2e /opt/arthas/demo/com/example/arthas/DemoController.class
线上应用诊断与调试利器——Arthas文章插图
此时 , 无需重启应用 , 我们重新访问刚才的controller , 会发现返回结果已经成功更改了 。
线上应用诊断与调试利器——Arthas文章插图
案例2
某燃气系统由于被众多地区的燃气公司所使用 , 所以版本繁多 , 经历过很多轮的测试 , 其中比较耗时的当属性能测试了 。 以往性能测试工作通常耗时很长 , 主要是性能测试人员并不一定熟悉项目代码 , 导致压力测试出现问题的时候不容易找到问题的所在 。
在本次的表具接口的性能测试中 , 我们使用Arthas工具进行故障的快速定位 , 大幅减少了性能测试的时间 , 达到了很好的效果 。
本次压力测试的过程中我们发现 , 当并发达到一定数量的时候系统会卡死 , 大量新的请求会超时 。 使用dashboard查看发现系统的大量线程处于block或者wating中 。
线上应用诊断与调试利器——Arthas文章插图
使用trace命令 , 将压力测试的方法进行监控 , 并保存到日志文件中 , 接着重新跑一轮压力测试 。
trace -n 150000 com.towngas.tcis.interfaces.nb.NbInfoServlet getService >> tt-2020-10-17-NbServlet-getService监控日志 , 当用户数达到500+的时候果然发现了问题
线上应用诊断与调试利器——Arthas文章插图
继续使用trace命令跟踪 , 发现了可能出现问题的方法
线上应用诊断与调试利器——Arthas文章插图
使用jad命令反编译该代码可以看到HttpClient并没有被立即关闭 , 使用release的释放后关闭通常没有问题 , 但是释放资源有一个过程通常是180秒 , 所以如果短时间有大量接口调用 , 会导致打开的socket连接数量超过系统设定值 。 找到原因后问题得以顺利解决 , 压力测试得以顺利完成 。