【Arthas】基本使用
接口响应不符合预期,怀疑参数没传正确或者接口响应慢等问题,按以前的做法是在程序中打印日志记录入参、响应时间再进行部署,整个过程耗时长,通过 Arthas Java应用诊断利器,可以直接在线上拦截接口入参,排查各方法耗时等问题
使用场景
主要的场景如下:
- 是否需要一个全局视角来查看系统的运行状况?
- 系统CPU升高了,到底是哪里占用了CPU?
- 运行的多线程有死锁吗?有阻塞吗?
- 有什么方法可以监控到JVM的实时运行状态?
安装
可以在官方 Github 上进行下载,也可以在国内的码云 Gitee 下载。
github下载
wget https://alibaba.github.io/arthas/arthas-boot.jar
Gitee 下载
wget https://arthas.gitee.io/arthas-boot.jar
打印帮助信息
java -jar arthas-boot.jar -h
运行
image.pngjava -jar arthas-boot.jar 9557
常用命令
image.pngdashboard
image.png首先我们可以通过dashboard查看线程整体的运行情况,heap的消耗情况,以及运行时环境
thread 查看所有线程的状态
image.pngthrea id:查看具体某一个线程的具体信息
image.png
sc & sm
image.pngsc: search class
sm: search method
image.png
monitor:方法的执行监控
image.pngtrace: 查看方法中方法的耗时
[arthas@5555]$ trace --skipJDKMethod false demo.MathGame run
PrintStream 类的 print 方法占据了 87% 的时间,这是 JDK 自带的类,这说明我们程序本身并无耗时问题,但 MathGame 类的 primeFactors 方法抛出了异常,我们可以看看具体的异常,再思考怎么优化。
image.png
另外,trace 可以选择性地进行调用拦截,比如设置只拦截大于 20ms 的调用:
image.png[arthas@5555]$ trace demo.MathGame run '#cost > 20'
使用ognl进行条件过滤
image.png
watch:观测函数的调用情况
watch 查看真实的调用数据
拦截 primeFactors 方法抛出的异常:
image.png$ watch demo.MathGame primeFactors -e "throwExp"
小王从大到小、逐步分析,找出了问题的原因是 primeFactors 抛出了异常,修正参数后,程序恢复了正常。
image.pngtt
tt: Time Tunnel.记录下当前方法的每次调用环境现场
tt -t:记录调用信息
image.png
tt -i: 显示某次调用的详细信息
image.png
tt -l: List all the time fragments
image.png
tt -i [index] -p: 重做一次调用
image.png
profile 明确整体的耗时情况
profile 命令支持为应用生成火焰图,在 Arthas 终端输入以下命令:
开始对应用中当前执行的活动采样 30 秒,采样结束后默认会生成 HTML 文件
[arthas@5555]$ profiler start -d 30
打开 HTML 文件能看到这样的结构:
image.png
MathGame 类下的 run 方法占用了大部分的执行时间,接下来我们看看 run 方法内部的耗时情况。
CPU 占用过高
CPU 是程序运行的核心计算资源,一旦出现 CPU 占用过高,必定对大部分用户的访问耗时产生影响。针对这类问题,要定位出有问题的线程,并获取该线程当前执行的代码位置。
使用 top + jstack 命令可以定位这类问题(见参考资料三),Arthas 也提供了更便捷的一体化工具:
- 定位目标线程
调用线程看板,并刷新数据三次
image.png[arthas@5555]$ dashboard -n 3
DashBoard 刷新三次后,在最新状态中发现示例程序里自己的线程 “main” 占用不算高,说明程序运行正常。如果是要排错,这里就要找出 CPU 占用最高的用户线程的 ID。
- 查看目标线程执行的代码位置
image.png“1” 是上一步定位到的 main 的线程ID
[arthas@5555]$ thread 1
线程正在“睡觉”,没什么大问题。
生产环境的效果和测试不一样
有些时候你发现:测试环境正常,但生产就报错了。这类问题主要靠做好上线流程的管控,但也有可能是打包的依赖库出现冲突,造成程序行为不一致。接下来,我们看看怎么用 Arthas 反编译代码,以及怎么对比依赖库的版本。
- 反编译代码
image.pngdemo.MathGame 是目标类的全限定名
[arthas@5555]$ jad demo.MathGame
- 查看目标类所属的依赖包
image.pngdemo.MathGame 是目标类的全限定名
[arthas@5555]$ sc -d demo.MathGame
如果这里是依赖包,code-source 还可以显示所属包的版本。这样就可以对比本地的代码,从而在打包时设置正确的依赖版本。
内存溢出
生产问题中内存溢出也有不小的比例。内存溢出的关键是找出高内存占用的对象。命令行操作会比较麻烦,建议转储 Heap Dump 等文件后,通过 Eclipse Memory Analyzer(MAT) 等工具进行分析。
通过 IDEA 插件快速生成 Arthas 命令
image.png通过插件快速生成【拦截方法入参、返回值】命令
image.png
打开命令行下载并启动 Arthas,看到下面页面时选择相应的进程进行拦截,这里按 1 并按回车键完成
image.png
粘贴上面插件生成的 Arthas 命令,请求接口便可看到接口入参、返回值
image.png
分析方法调用耗时,使用 Arthas IDEA 插件选择【Trace】命令
image.png
在 Arthas 命令行上粘贴命令并请求接口,方法内部调用路径,并输出方法路径上的每个节点上耗时
image.png