Arthas 介绍
Arthas
(https://arthas.aliyun.com/doc/)是Alibaba开源的Java诊断工具。
当你遇到以下类似问题而束手无策时,Arthas
可以帮助你解决:
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到JVM的实时运行状态?
- 怎么快速定位应用的热点,生成火焰图?
- 怎样直接从JVM内查找某个类的实例?
安装方式
curl -L https://arthas.aliyun.com/install.sh | sh
上述命令会下载启动脚本文件 as.sh
到当前目录,直接在shell下面执行./as.sh
,就会进入交互界面。
我用的最高频的操作的就是它的trace
和watch
功能,
trace
https://arthas.aliyun.com/doc/trace.html 可以看到完整的调用链和各个耗时,比如下面查看demo.MathGame
的run
方法,耗时超过10ms
的请求,还有更多复杂的参数用法,需要查看手册
$ trace demo.MathGame run '#cost > 10'
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 41 ms.
`---ts=2018-12-04 01:12:02;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
`---[12.033735ms] demo.MathGame:run()
+---[0.006783ms] java.util.Random:nextInt()
+---[11.852594ms] demo.MathGame:primeFactors()
`---[0.05447ms] demo.MathGame:print()
watch
https://arthas.aliyun.com/doc/watch.html 观察到指定方法的调用情况。能观察到的范围为:返回值
、抛出异常
、入参
,比如下面,监控demo.MathGame
的primeFactors
方法,-x 2
表示输出结果的属性遍历深度
$ watch demo.MathGame primeFactors -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 32 ms, listenerId: 5
method=demo.MathGame.primeFactors location=AtExit
ts=2021-08-31 15:22:58; [cost=1.020982ms] result=@ArrayList[
@Object[][ // 参数
@Integer[1],
],
@MathGame[ // 对象
random=@Random[java.util.Random@31cefde0],
illegalArgumentCount=@Integer[44],
],
@ArrayList[ // 返回值
@Integer[2],
@Integer[2],
@Integer[26947],
],
]
快捷插件
因为手册上的命令、表达式,还是很有难度的,比较容易忘记,很多深层次好用的功能不容被挖掘,所有人搞了这个插件,良心大作啊,文档齐全,长时间更新,https://www.yuque.com/arthas-idea-plugin/help/pe6i45
比如,常用的 watch
命令,只用在ide里,点点点就能生成命令,到服务器上粘贴运行即可,非常方便,强烈推荐
trace
https://arthas.aliyun.com/doc/trace.html 可以看到完整的调用链和各个耗时,比如下面查看demo.MathGame
的run
方法,耗时超过10ms
的请求,还有更多复杂的参数用法,需要查看手册
$ trace demo.MathGame run '#cost > 10'
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 41 ms.
`---ts=2018-12-04 01:12:02;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
`---[12.033735ms] demo.MathGame:run()
+---[0.006783ms] java.util.Random:nextInt()
+---[11.852594ms] demo.MathGame:primeFactors()
`---[0.05447ms] demo.MathGame:print()
watch
https://arthas.aliyun.com/doc/watch.html 观察到指定方法的调用情况。能观察到的范围为:返回值
、抛出异常
、入参
,比如下面,监控demo.MathGame
的primeFactors
方法,-x 2
表示输出结果的属性遍历深度
$ watch demo.MathGame primeFactors -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 32 ms, listenerId: 5
method=demo.MathGame.primeFactors location=AtExit
ts=2021-08-31 15:22:58; [cost=1.020982ms] result=@ArrayList[
@Object[][ // 参数
@Integer[1],
],
@MathGame[ // 对象
random=@Random[java.util.Random@31cefde0],
illegalArgumentCount=@Integer[44],
],
@ArrayList[ // 返回值
@Integer[2],
@Integer[2],
@Integer[26947],
],
]
arthas 还有很多更高级的用法,但是一些命令容易忘记,表达式又有一定的语法门槛也难记忆,好消息是在插件里面都有封装,我们只需要点点点就能快速的生成命令,便于在服务器上粘贴执行了,强烈推荐
https://www.yuque.com/arthas-idea-plugin/help/pe6i45
热部署
经常会遇到因为某一小块代码逻辑写得不对,导致需要重续部署的情况,这样又是一杯咖啡的时间过去了,想不加班都难啊,所以 arthas 提供了热部署功能 https://arthas.aliyun.com/doc/redefine.html 单独编译某一个类文件,然后将其执行热部署
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
mc /tmp/UserController.java -d /tmp
redefine /tmp/com/example/demo/arthas/user/UserController.class
但是实际情况会复杂一些,因为我们需要把本地编译好的文件上传到服务器上,非常的麻烦,上面说的插件又帮我解决了这一问题, https://www.yuque.com/arthas-idea-plugin/help/pwxhb4 支持剪切板 base64 的方式复制粘贴,但是更推荐配置一个阿里云 oss 作为中转跳板上传和下载。
运维监控
有时候一些异常只会抽风式偶尔出现,想抓现行,比较困难,所以需要一个监控。比如像找到 cpu 达到80%的时候的最忙碌的线程的 top n,可以使用 arthas 的 thread -n 10
功能,但是 arthas 是交互式的,需要我们补充点管道的知识,也就是下面的mknod arthas_input p
#!/bin/bash
ctime=$(date "+%H-%M-%S")
cpu_percent=`top -n 1 | grep Cpu| awk -F " " '{print int($2)}'`
if [ ${cpu_percent} > 80 ] ; then
echo "${ctime}开始采集最占 cpu 的线程"
mknod arthas_input p
exec 8<> arthas_input
./as.sh <&8 &
echo -e "1\n" >> arthas_input
echo "thread -n 10 > $(pwd)/arthas.${cpu_percent}.${ctime}.result" >> arthas_input
echo "quit" >> arthas_input
rm -f arthas_input
sleep 2s
fi
这样即使半夜或者在公交车上,或者在打游戏,都不慌了,报警过后直接看日志就行了。当然是 nohup 的方式启动该脚本
同理之前还遇到过在偶发的线上某个接口特别慢,超时的错误提醒,所以呢,我也在线上直接使用了这个脚本,值抓取那些耗时超过 2s 的请求日志
#!/bin/bash
ctime=$(date "+%H-%M-%S")
mknod arthas_input p
exec 8<> arthas_input
./as.sh <&8 &
echo -e "1\n" >> arthas_input
echo "trace xxxx getCourseDetail '#cost > 2000' >> $(pwd)/arthas.trace.log" >> arthas_input
最终根据日志也顺利定位解决了问题。
👇 下面是我的公众号,高质量的博文我会第一时间同步到公众号,给个关注吧!