实战!使用 阿里 Arthas 工具分析 CPU 飙高

来源:码猿技术专栏


Arthas 是阿里开源的 Java 诊断工具,相比 JDK 内置的诊断工具,要更人性化,并且功能强大,可以实现许多问题的一键定位,而且可以一键反编译查看源码,甚至是直接进行生产代码热修复,实现在一个工具内快速定位和修复问题的一站式服务。


今天,我就带你使用 Arthas 定位一个 CPU 使用高的问题,系统学习下这个工具的使用。


首先,下载并启动 Arthas:

curl -O https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar


启动后,直接找到我们要排查的地方 JVM 进程,然后可以看到 Arthas 附加进程成功:

[INFO] arthas-boot version: 3.1.7
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 12707
  [2]: 30724 org.jetbrains.jps.cmdline.Launcher
  [3]: 30725 org.geekbang.time.commonmistakes.troubleshootingtools.highcpu.HighCPUApplication
  [4]: 24312 sun.tools.jconsole.JConsole
  [5]: 26328 org.jetbrains.jps.cmdline.Launcher
  [6]: 24106 org.netbeans.lib.profiler.server.ProfilerServer
3
[INFO] arthas home: /Users/zhuye/.arthas/lib/3.1.7/arthas
[INFO] Try to attach process 30725
[INFO] Attach process 30725 success.
[INFO] arthas-client connect 127.0.0.1 3658
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O   |  .--. ''--.  .--'|  '--'  | /  O   '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |      |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'




wiki      https://alibaba.github.io/arthas
tutorials https://alibaba.github.io/arthas/arthas-tutorials
version   3.1.7
pid       30725
time      2020-01-30 15:48:33


输出 help 命令,可以看到所有支持的命令列表。今天,我们会用到 dashboard 、thread 、jad 、watch 、ognl 命令,来定位这个 HighCPUApplication 进程。


你可以通过官方文档:https://arthas.aliyun.com/doc/commands.html,查看这些命令的完整介绍:


实战!使用 阿里 Arthas 工具分析 CPU 飙高


dashboard 命令用于整体展示进程所有线程、内存、GC 等情况,其输出如下:


实战!使用 阿里 Arthas 工具分析 CPU 飙高


可以看到,CPU 高并不是 GC 引起的,占用 CPU 较多的线程有 8 个,其中 7 个是 ForkJoinPool.commonPool。


ForkJoinPool.commonPool 是并行流程默认使用的线程池。


所以,此次 CPU 高的问题,应该出现在某段并行流的代码上。


接下来,要查看最繁忙的线程在执行的线程栈,可以使用 thread -n 命令。这里,我们查看下最忙的 8 个线程:

thread -n 8


输出如下:


实战!使用 阿里 Arthas 工具分析 CPU 飙高


可以看到,由于这些线程都在处理 MD5 的操作,所以占用了大量时间 CPU 资源。我们希望分析出代码中哪些逻辑可能会执行这个操作,所以需要从方法栈上找出我们自己写的类,并重点关注。


由于主线程也参与了 ForkJoinPool 的任务处理,因此我们可以通过主线程的栈看到需要重点关注 org.geekbang.time.commonmistakes.troubleshootingtools.highcpu.HighCPUApplication 类的 doTask 方法。

接下来,使用 jad 命令直接对 HighCPUApplication 类反编译:

jad org.geekbang.time.commonmistakes.troubleshootingtools.highcpu.HighCPUApplication


可以看到,调用的路径是 main->task()->doTask(),当 doTask 方法接收到的 int 参数等于某个常量的时候,会进行 1 万次的 MD5 操作,这就是耗费 CPU 的来源。那么,这个魔法值到底是多少呢?


实战!使用 阿里 Arthas 工具分析 CPU 飙高


你可能想到了,通过 jad 命令继续查看 User 类即可。这里因为是 Demo,所以我没有给出很复杂的逻辑。在业务逻辑很复杂的代码中,判断逻辑不可能这么直白,我们可能还需要分析出 doTask 的“慢”会慢在什么入参上。


这时,我们就可以使用 watch 命令来观察方法入参。如下命令,表示需要监控耗时超过 100 毫秒的 doTask 方法的入参,并且输出入参,展开 2 层入参参数:

watch org.geekbang.time.commonmistakes.troubleshootingtools.highcpu.HighCPUApplication doTask '{params}' '#cost>100' -x 2


可以看到,所有耗时较久的 doTask 方法的入口都是 0,意味着 User.ADMN_ID 常量应该是 0。


实战!使用 阿里 Arthas 工具分析 CPU 飙高


最后,我们使用 ognl 命令来运行一个表达式,直接查询 User 类的 ADMIN_ID 静态字段来验证是不是这样,得到的结果果然是这样 0:


[arthas@31126]$ ognl '@org.geekbang.time.commonmistakes.troubleshootingtools.highcpu.User@ADMIN_ID'
@Integer[0]


需要额外说明的是,由于 monitor、trace、watch 等命令是通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此诊断结束要执行 shutdown 来还原类或方法字节码,然后退出 Arthas。


在这个案例中,我们通过 Arthas 工具排查了高 CPU 的问题:



可见,使用 Arthas 来定位生产问题根本用不着原始代码,也用不着通过增加日志来帮助我们分析入参,一个工具即可完成定位问题、分析问题的全套流程。


对于应用故障分析,除了阿里 Arthas 之外,还可以关注去哪儿的Bistoury :https://github.com/qunarcorp/bistoury工具,其提供了可视化界面,并且可以针对多台机器进行管理,甚至提供了在线断点调试等功能,模拟 IDE 的调试体验。



展开阅读全文

页面更新:2024-05-01

标签:阿里   工具   常量   线程   实战   逻辑   进程   命令   代码   操作   方法

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top