背景
玩了很久的Arthas,觉得是线上排除问题的神器,也推荐过同事解决了一些棘手问题,然后在组内做了一次分享,总结了一下能用的实战场景和常用的命令
定义
Arthas 是 Alibaba 在 2018 年 9 月开源的 Java 诊断工具。支持 JDK6+,采用命令行交互模式,提供 Tab 自动补全,可以方便的定位和诊断线上程序运行问题。
官方文档:https://alibaba.github.io/arthas
使用场景
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到JVM的实时运行状态?
- 怎么快速定位应用的热点,生成火焰图?
全局监控
使用dashboard查看程序的 线程、内存、GC、运行环境信息
查看接口响应时间
当接口反应慢的时候可以用trace命令来查看方法内部调用路径,并输出方法路径上的每个节点上耗时
常用例子:trace *.Testcontroller test -n 1 ‘#cost > 10’
参数说明:
| 参数名称 | 参数说明 |
|---|---|
| 参数名称 | 参数说明 |
| class-pattern | 类名表达式匹配 |
| method-pattern | 方法名表达式匹配 |
| condition-express | 条件表达式 |
| [E] | 开启正则表达式匹配,默认为通配符匹配 |
| [n:] | 命令执行次数 |
| #cost | 方法执行耗时 |
查看方法入参,返回值,异常
当异常没有打出来的时候或者想看一下被调用方法的入参的时候
常用例子:watch *.Testcontroller test ‘{params,returnObj,throwExp}’ -x 3 -s
| 参数名称 | 参数说明 |
|---|---|
| class-pattern | 类名表达式匹配 |
| method-pattern | 方法名表达式匹配 |
| express | 观察表达式 |
| condition-express | 条件表达式 |
| [b] | 在方法调用之前观察 |
| [e] | 在方法异常之后观察 |
| [s] | 在方法返回之后观察 |
| [f] | 在方法结束之后(正常返回和异常返回)观察 |
| [E] | 开启正则表达式匹配,默认为通配符匹配 |
| [x:] | 指定输出结果的属性遍历深度,默认为 1 |
热更新
当你突然发现刚更新的代码有一个判断出错了,发一次走流程需要很长时间,也影响用户体验,这个时候可以使用热更新,在不停止程序的情况下更新掉错误,热更新只满足方法里的改动更新,如果是添加了方法或者删除方法,将更新失败
第一步:反编译代码,第二步查看ClassLoader,第三步编译,第四步:更新
- jad --source-only com.example.demo.arthas.user.TestController > /tmp/TestController.java
- $ sc -d *TestController| grep classLoaderHash
classLoaderHash 452c5c14
classLoaderHash 452c5c14 - mc -c 452c5c14 /tmp/TestController.java -d /tmp
- $ redefine -c 452c5c14 /tmp/TestController.class
redefine success, size: 1
这里我一般会缩减为两步,上面的第二步和第四步,直接把class文件放在tmp下面就行了 - $ sc -d *TestController| grep classLoaderHash
- $ redefine -c 452c5c14 /tmp/TestController.class
查看线程情况
当cpu飙升的时候可以查看线程cpu占比,线程堆栈信息
常用例子:thread -n 3:展示当前最忙的前N个线程并打印堆栈,通过堆栈可以查到具体是那个方法导致cpu占比过高
| 参数名称 | 参数说明 |
|---|---|
| id | 线程id |
| [n:] | 指定最忙的前N个线程并打印堆栈 |
| [b] | 找出当前阻塞其他线程的线程 |
| [i ] | 指定cpu使用率统计的采样间隔,单位为毫秒,默认值为200 |
| [–all] | 显示所有匹配的线程 |
生成火焰图
要跟踪哪个事件(cpu, alloc, lock, cache-misses等),默认是cpu,可以生成火焰图
| 参数名称 | 参数说明 |
|---|---|
| action | 要执行的操作 |
| actionArg | 属性名模式 |
| [i:] | 采样间隔(单位:ns)(默认值:10’000’000,即10 ms) |
| [f:] | 将输出转储到指定路径 |
| [d:] | 运行评测指定秒 |
| [e:] | 要跟踪哪个事件(cpu, alloc, lock, cache-misses等),默认是cpu |
生成火焰图步骤
1.profiler start 开始取样
2.profiler stop 停止取样,生成火焰图,但是火焰图看起来太乱,建议还是生成html类型(profiler stop --format html)
打开html显示如下:百分号是这个线程的cpu的占比,可以一直往里点找到程序的方法