记Arthas实现一次CPU排查与代码热更新

简介: 本文介绍如何使用Arthas排查线上Java应用CPU占用过高问题。通过`thread`定位高耗能线程,`watch`监控方法调用与异常,结合`jad`反编译与`redefine`实现热更新,无需重启服务即可修复代码,提升线上问题响应效率。适用于SpringBoot + JDK8环境。

1.前言
背景
线上代码经常会出现CPU占用过高的情况,按以往经验我会使用top指令,进一步借助于jstack去查看具体信息从而进行问题排查,但基本上都逃不过需要重新发包的局面,即使是一个增量包,应用也需要短暂停启。后来运维大兄弟让我试一下Arthas,说是可以进行代码的热更新操作,正好来试一下。关于Arthas的安装与基础使用可以参考我这两篇:
Arthas安装与监听SpringBoot应用
Arthas基础指令使用说明
环境
JDK1.8
SPringBoot 2.2.2
Arthas
Linux
测试代码:
思路
2.thread -b 查看是否有阻塞线程
thread -b, 找出当前阻塞其他线程的线程,执行完之后并未发现,说明该线程并非一直阻塞,一直执行的
3.thread 查看占用最高的线程
当thread之后不跟参数时,显示当前全部线程信息,我觉得 thread -n 10,展示前10应该就够用,可根据实际需要自己决定。
下图可以很直观的看出,我们的应用瞬间占用了77%的CPU(这里我是发起请求瞬间,通过thread查看的,所以比较直观,生产环境应该只有阻塞,死锁这种状态才会比较直观)
4.thread id 查看具体信息
在上一步基础上,我们进一步查看,thread 15(因为上面的ID=15)
他的大致意思就是:线程在等待一个条件从而继续执行,可以看到方法是在执行LinkedBlockingQueue.take方法时候,查看这个方法的API提示如下:
其中:AtomicInteger是保证高并发情况下的原子性,ReentrantLock标识可重入锁,都是JUC包下需要了解的这里不赘述,需要的百度了解下。
这段代码关键点就在于:notEmpty.await(),从队列中消费数据,当队列为空是,线程阻塞,所以我们大致知道现在出现的问题是线程阻塞,但是还是不知道具体哪行代码的问题。
如果能够明确知道这次更改了哪些代码,可以直接执行步骤6,不知道的话可以通过步骤5来定位问题。
5.watch 查看哪个Controller执行了代码
这个脚本可以检测一切通过DispatcherServlet匹配Handler的方法,也就是进入Controller的请求,如下:
找到了对应的代码之后,我们来进一步观察异常信息,这里可能会有一个问题:就是我明明能通过日志去查看错误信息,为什么还需要这么繁琐的去操作。我的业务场景是:日志还是非常大的,刚捞到就被刷过去了,这时候定位日志不是很好操作,当然想捞下来日志肯定也是可以的,也很直观,我一般也都是去查看日志进行问题定位,这里也是提供一个思路。
6.watch 该方法异常信息
如上,错误很直观的提示了出来,下面就可以修复解决了,这里我们也可以通过trace指令,查看执行时长:
返回信息如下,也可以看到错误信息,和每个方法执行的时长
7.jad 反编译热更新
在上面知道问题之后,我们就来定位问题就好了,
命令:jad 类全路径 方法名
此时代码就被反编译了,为了能够更改,所以我们需要输出为java文件
指令:jad com.arthas.controller.OrderController > /tmp/OrderController.java
即:jad 类全路径 方法名 > 存储路径/存储名称
然后到tmp路径下vi修改java文件即可,修改完成之后,查看对应的classloader为编译做准备
但是这里编译出错了,官方提示:
所以我们本地编译好class文件,上传上去是一样的
编译前调用
更新前代码
Java
运行代码
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping(value = "/bigThread")
@ResponseBody
public String bigThread(int id) {
ArthasService.test();
while (true) {
Thread t2 = new Thread();
t2.start();
id ++;
if(100000 == id) {
return String.valueOf(id);
}
}
}
更新后代码
Java
运行代码
复制代码
1
2
3
4
5
6
7
8
@RequestMapping(value = "/bigThread")
@ResponseBody
public String bigThread(int id) {
ArthasService.test();
Thread t2 = new Thread();
t2.start();
return "success";
}
编译指令
Java
运行代码
复制代码
1
2
3
[arthas@13190]$ redefine /tmp/OrderController.class
redefine success, size: 1, classes:
com.arthas.controller.OrderController
编译后调用三次
Java
运行代码
复制代码
1
2
3
4
5
6
7
8
9
10
11
---ts=2020-08-19 15:52:02;thread_name=http-nio-0.0.0.0-8080-exec-3;id=f;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6---[5.609405ms] com.arthas.controller.OrderController:bigThread()
`---[0.204675ms] com.arthas.service.ArthasService:test() #20

---ts=2020-08-19 15:52:04;thread_name=http-nio-0.0.0.0-8080-exec-4;id=10;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6---[3.900149ms] com.arthas.controller.OrderController:bigThread()
`---[0.14636ms] com.arthas.service.ArthasService:test() #20

---ts=2020-08-19 15:52:04;thread_name=http-nio-0.0.0.0-8080-exec-5;id=11;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1f1c7bf6---[1.90945ms] com.arthas.controller.OrderController:bigThread()
`---[0.147353ms] com.arthas.service.ArthasService:test() #20
可以发现时间从6734.666529ms变成3ms左右,说明热更新的代码生效了

相关文章
|
2月前
|
Arthas 监控 Java
arthas 基础指令
Arthas简介:通过dashboard查看线程状态、CPU占用等;jad反编译类文件;thread分析线程堆栈及阻塞情况;watch监控方法执行耗时与参数;支持quit退出连接或stop彻底终止。适用于Java进程诊断,操作便捷,功能强大。(239字)
|
运维 监控 网络协议
JAVA 线上故障排查完整套路,从 CPU、磁盘、内存、网络、GC
JAVA 线上故障排查完整套路,从 CPU、磁盘、内存、网络、GC
1205 0
|
5月前
|
Arthas 运维 监控
一次线上CPU飙高排查实录:从Arthas到JVM调优的深入之旅
本文记录了一次线上Java应用CPU使用率异常升高的故障排查过程。通过使用阿里巴巴开源工具Arthas,快速定位到问题根源:日志切面中存在性能缺陷的正则表达式在处理超长字符串时引发“回溯爆炸”,导致CPU资源耗尽。文中详细介绍了排查步骤、问题分析及解决方案,包括利用Arthas进行实时监控、线程分析、方法监控和在线热更新修复。最后总结了排查经验与技术启示,强调工具掌握、性能意识与防御式编程的重要性。
844 0
|
Arthas 监控 Java
开源Java诊断工具Arthas:开篇之watch实战
还在为排查Java程序线上问题头痛吗,看我们用阿里开源的诊断神器 Arthas 来帮您
1329 1
|
2月前
|
Arthas 存储 运维
记Arthas实现一次CPU排查与代码热更新
本文介绍如何使用Arthas排查Java应用CPU占用过高问题,通过thread、watch、jad等指令定位线程阻塞与异常代码,并实现无需重启的热更新修复,结合profile生成火焰图进行性能分析,提升线上问题处理效率。
记Arthas实现一次CPU排查与代码热更新
|
2月前
|
Arthas 监控 前端开发
arthas精准定位Java应用CPU负载过高问题
通过Arthas的watch命令监控DispatcherServlet的getHandler方法,快速定位Spring MVC中处理请求的Controller;结合反编译功能,实时查看目标代码,提升排查效率。
|
9月前
|
Arthas 存储 监控
Arthas heapdump(dump java heap, 类似 jmap 命令的 heap dump 功能)
Arthas heapdump(dump java heap, 类似 jmap 命令的 heap dump 功能)
673 8
|
9月前
|
Arthas 监控 Java
Arthas thread(查看当前JVM的线程堆栈信息)
Arthas thread(查看当前JVM的线程堆栈信息)
1657 10
|
10月前
|
Arthas 监控 Java
Arthas profiler(使用async-profiler对应用采样,生成火焰图)
Arthas profiler(使用async-profiler对应用采样,生成火焰图)
1599 10
MyBatis-Plus-Join关联查询
MyBatis-Plus-Join关联查询
851 2