Arthas 快速入门
封面来源:本文封面来源于 Arthas 官网,如有侵权,请联系删除。
官方文档:arthas
本文参考:Java 诊断神器Arthas真有那么香?它到底能解决什么问题 | Arthas 教程实操 | 线上问题排查思路和手段
测试代码:springboot-study/arthas-demo at master · mofan212/springboot-study
1. Arthas 的简介
今天同事问我会不会使用 Arthas 来查看接口的耗时,奈何本人才蔽识浅,仅仅使用过它的 jad
命令来反编译类文件。突然想起曾经收藏过一个关于如何使用 Arthas 的视频,那就利用这个今晚的时间学习下吧。
简介
Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 Load、内存、GC、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。
诸如此类的工具就和 Mac Book 一样,当你在考虑要不要买 Mac Book 时,那就不要购买;当你不知道 Arthas 有什么用,那就不用学。
能解决什么问题
Arthas 是阿里巴巴出品的线上 JVM 监控诊断利器,它适用于:
-
有没有一个全局 JVM 运行时监控?能够显示 CPU、线程、内存、堆栈等信息
-
CPU 飙高是什么原因造成的?
-
接口没反应、卡住了,是不是死锁了?
-
CTO 说你们这个接口太慢了,要优化一下,如何准确找出耗时的代码?
-
写的代码没有执行,是部署的分支不对,还是压根没提交?
-
线上有一个低级错误,改起来很简单,能不能在不重启应用的情况下,进行类替换,达到热部署?
2. 快速入门
2.1 安装与启动
进入 下载 | arthas 页面,可以从 Maven 仓库下载,也可以前往 Github Releases 页下载,下载完成后,解压文件。
而在 MacOS / Linux 环境下,可以直接执行以下命令下载:
1 | wget https://arthas.aliyun.com/arthas-boot.jar |
在启动 Arthas 前,需要有一个 JVM 进程。先运行 main()
方法:
1 |
|
在有 arthas-boot.jar
的目录下,使用 java -jar
的方式启动:
1 | java -jar arthas-boot.jar |
运行后会列出所有存在的 Java 进程,找到需要连接的进程:
之后输入目标进程对应的序号,当界面成功显示 Arthars 的 Banner 时,证明连接成功:
2.2 基本命令的使用
help
查看当前 Arthas 版本支持的指令,或查看具体指令的使用说明。
或者在某一命令后使用 -h
选项,查看该命令的用法和示例,比如:
1 | dashboard -h |
根据示例,输入 dashboard
,查看 JVM 运行时监控:
按 Ctrl + C
退出。
thread
thread
命令可以查看当前线程信息、线程的堆栈。
运行下列代码:
1 |
|
利用 Arthas 连接到对应的进程,执行 thread
命令:
目标线程的序号是 11
,运行下列命令查看 11
号线程对应的信息:
jad
现在需要打印出一些好习惯:多读书,多看报,少吃零食,多睡觉。
运行下列代码:
1 |
|
控制台打印出:
多读书,多看报
只打印了前半句,这是怎么回事呢?
使用 jad
跟上目标类的全限定名称,反编译目标类:
上述反编译结果有两个问题:
- 在
doSomething()
方法中只调用了readAndSleep()
方法,没有其他内容,导致只打印了前半句; readAndSleep()
方法中的中文乱码。
针对第一个问题,查看源码后发现代码被注释:
1 | public class GoodHabit { |
放开注释,重新运行程序,控制台打印出:
多读书,多看报 少吃零食,多睡觉
第二个问题的解决则是要在启动 Arthas 时设置 Arthas 向控制台输出内容使用的默认编码:
1 | java -Dfile.encoding=UTF-8 -jar arthas-boot.jar |
2.3 方法的监测
首先推荐一个 IDEA 插件:Arthas Idea,利用该插件可以很方便地生成 Arthas 命令。
watch
watch
命令用于监测方法执行数据。
运行以下代码,循环打印 Car
的信息:
1 | private Car getCar(String carName, BigDecimal carPrice) { |
此时需要监测 getCar()
方法,鼠标右击目标方法,选择 Arthas Command
,然后再选择 Watch
生成 Arthas 命令:
最终生成的命令如下:
1 | watch indi.mofan.ArthasDemo getCar '{params,returnObj,throwExp}' -n 5 -x 3 |
这表示:监测 indi.mofan.ArthasDemo
类中的 getCar()
方法,获取方法调用时使用的参数、返回值和异常信息,共监测 5 次,输出的对象属性遍历深度为 3。
如果跟踪的字段或对象过大,会导致输出的内容太多,甚至可能因为控制台的限制而丢失信息。此时可以尝试将 watch
命令的输出重定向到文件中,比如:
1 | watch indi.mofan.ArthasDemo getCar '{params,returnObj}' -n 5 -x 3 > /path/to/output.txt |
trace
trace
命令用于获取方法内部调用路径,并输出方法路径上的每个节点上耗时。
利用 Arthas Idea 插件生成相应命令:
1 | trace indi.mofan.ArthasDemo getCar -n 5 --skipJDKMethod false |
这表示:监测 5 次 indi.mofan.ArthasDemo
类中的 getCar()
方法,并且不跳过 JDK 中的方法。
执行 trace
命令后,耗时占比最高的部分会高亮显示。
stack
stack
命令用于输出当前方法被调用的调用路径。
利用 Arthas Idea 插件生成相应命令:
1 | stack indi.mofan.ArthasDemo getCar -n 5 |
这表示:监测 5 次 indi.mofan.ArthasDemo
类中的 getCar()
方法的被调用路径。
monitor
monitor
命令用于方法执行监控。
利用 Arthas Idea 插件生成相应命令:
1 | monitor indi.mofan.ArthasDemo getCar -n 10 --cycle 10 |
这表示:循环 10 次,每次调用 10 次 indi.mofan.ArthasDemo
类中的 getCar()
方法时的执行信息。
2.4 错误定位
死循环的定位
运行以下代码,这段代码会造成 死循环:
1 | private void deadLoop() { |
使用 dashboard
查看线程信息与内存信息:
main()
线程的 CPU 使用率达到 90%,内存中的 nonheap
和 metaspace
使用率非常高。
再使用 thread -n 3
查看当前 3 个最忙的线程:
死锁的定位
运行以下代码,这段代码会造成 死锁:
1 | private void deadLock() { |
利用 thread
全局查看线程信息:
可以看到当前有 27 个线程,其中有 2 个线程被阻塞。
还可以利用 thread -b
找出当前阻塞其他线程的线程:
2.5 时空隧道
tt
命令生成方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测。
记录每次调用方法的环境现场:
1 | tt -t 类全限定名 方法名 |
显示 tt
命令记录的时间片段:
1 | tt -l |
筛选出目标方法的时间片段:
1 | tt -s 'method.name=="目标方法名称"' |
查看某次方法的调用信息:
1 | tt -i 索引值 |
其中的索引值为执行 tt -t
、tt -l
等命令时第一列的值。
tt
命令保存了某次调用的所有现场信息,因此可以重做一次调用:
1 | tt -i 索引值 -p |
2.6 生成火焰图
profiler
命令可以生成应用热点的火焰图。
启动 profiler
:
1 | profiler start |
获取已采集的用例数量:
1 | profiler getSamples |
查看 profiler
状态(查看当前 profiler
在采样哪种 event
和采样时间):
1 | profiler status |
默认生成的是 CPU 的火焰图,即 event
为 cpu
,可以使用 --event
指定采样 event
。
停止采样:
1 | profiler stop |
停止采样后,默认生成 HTML 格式的结果文件。
3. 学习资源
第一学习资源当然是官网 arthas,官网除了提供 详尽的文档 外,还提供了 在线教程,让用户在实践中学习。
除此之外,在 Github 的 arthas 托管仓库中,Issues 中有个名为 user-case
的 Labels,这下面记录了 Arthas 的使用实例与最佳实践。