使用Arthas排查线上Java进程CPU飙升

VIP/
在Java应用的生产环境中,CPU使用率突然飙升至90%以上是运维人员最头疼的问题之一。传统的排查方式如重启服务、离线分析线程dump,不仅耗时费力,还可能因重启服务扩大故障影响范围。根据阿里中间件团队的统计,80%的线上故障源于性能问题,平均每起故障造成的直接损失超过10万元。
阿里巴巴开源的Arthas作为Java诊断神器,支持在不重启应用的情况下,通过一系列命令快速定位CPU瓶颈,成为线上诊断的”瑞士军刀”。本文将详细介绍如何使用Arthas三步定位CPU飙升问题,并提供完整的实战案例。
一、Arthas简介与快速安装
1.1 什么是Arthas?
Arthas是阿里巴巴开源的Java诊断工具,可以在不重启、不改代码、不停机的情况下进行线上问题排查。它支持:
查看JVM状态和实时监控
动态跟踪方法调用
监控SQL/接口/线程性能
分析CPU飙高、内存泄漏、接口变慢等问题
1.2 快速安装与启动
# 下载Arthas
curl -O https://arthas.aliyun.com/arthas-boot.jar
# 启动并连接目标Java进程
java -jar arthas-boot.jar
启动后,Arthas会列出当前所有Java进程,输入对应编号即可attach到目标进程。对于生产环境,建议使用指定PID的方式启动:
java -jar arthas-boot.jar 12345  # 12345为目标进程PID
二、CPU飙升排查完整流程
2.1 宏观诊断:快速定性问题类型
首先通过系统命令确认问题范围:
# 查看系统整体CPU使用情况
top
# 按P键按CPU使用率排序,找到高CPU的Java进程
top -c
根据CPU使用情况快速判断问题类型:
现象
核心指标
判断方向
下一步操作
User (us) 高
us > 50%, sy 低
业务代码问题(死循环、复杂计算、正则回溯)
进入微观定位阶段
System (sy) 高
sy > 30%
并发/资源竞争(锁竞争激烈、线程上下文切换过高)
查vmstat/锁等待
GC抖动
us高 + 内存震荡
JVM垃圾回收(频繁Full GC)
转至内存与GC排查
2.2 三步定位法:Arthas核心排查流程
第一步:全局监控,快速定位问题线程
使用dashboard命令获取JVM全局视图:
# 查看实时仪表板(最常用)
dashboard
# 每3秒刷新一次
dashboard -i 3000
# 自动刷新10次后退出
dashboard -n 10
重点关注三个区域:
JVM基本信息:内存使用、GC情况
线程列表:按CPU使用率排序
系统信息:CPU、内存、负载
第二步:线程剖析,定位问题代码行
使用thread命令找出最耗CPU的线程:
# 查看CPU使用率最高的前5个线程
thread -n 5
# 采样1秒,避免抓到瞬间毛刺
thread -n 3 -i 1000
# 查看指定线程的详细堆栈
thread 12345
关键输出解读:
cpuUsage:显示该线程占用了单个CPU核心的百分比(如90%表示占满了一个核)
Stack:关注堆栈顶部的包名(com.your.company…),这就是具体的代码行号
示例输出:
Threads Top 3, sample interval 1000ms:
Thread 12345: cpuUsage=95.2%
  at com.your.biz.service.ProcessService.process(ProcessService.java:123)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
第三步:代码分析,确认问题根源
找到高CPU线程后,使用jad命令反编译类查看具体代码:
# 反编译可疑类
jad com.example.service.DataProcessor
通过反编译结果,重点检查是否存在:
无限循环(未正确设置退出条件)
频繁执行的耗时操作(如大量字符串拼接、复杂计算)
不合理的递归(未控制深度导致无限递归)
2.3 进阶分析:方法级性能追踪
如果问题较复杂,可以使用更精细的分析工具:
使用trace追踪方法调用耗时
# 追踪指定方法的内部调用耗时
trace com.example.service.OrderService getOrderDetail
# 只追踪耗时超过100ms的调用
trace com.example.service.* * ‘#cost>100’ -n 5
# 显示JDK方法调用,对IO操作排查至关重要
trace -E com.xxx.service.*ServiceImpl.* -n 5 –skipJDKMethod false -d 3000
使用watch监控方法入参/返回值
# 监控方法入参和返回值
watch com.example.service.UserService getUser ‘{params, returnObj}’ -x 3
# 只监控耗时超过100ms的调用
watch com.example.service.UserService getUser ‘{params}’ ‘#cost>100’ -x 2
使用profiler生成火焰图
对于复杂问题,火焰图能直观展示CPU消耗热点:
# 开始CPU采样,持续60秒
profiler start -d 60
# 停止分析并生成HTML格式火焰图
profiler stop –format html
火焰图解读:
横轴:方法的CPU占用时间(越长表示占用CPU越多)
纵轴:方法调用栈(从上到下是调用关系)
颜色:仅用于区分不同方法
三、常见CPU飙升场景与解决方案
3.1 死循环/无限循环
特征:线程状态为RUNNABLE,调用栈反复出现同一方法。
错误示例:
// 错误示例:缺少退出条件
while (true) {
    processData();
}
正确示例:
// 正确示例:添加合理的退出条件
while (hasMoreData()) {
    processData();
}
排查命令:
# 找到高CPU线程
thread -n 3 -i 1000
# 查看线程堆栈
thread <线程ID>
# 反编译相关类
jad com.example.ProblemService
3.2 正则回溯陷阱
特征:复杂文本匹配时CPU突增。
错误示例:
// 错误示例:会导致指数级计算
String pattern = “.*a.*b.*c.*”;
正确示例:
// 正确示例:使用非贪婪匹配或更精确的模式
String pattern = “[^a]*a[^b]*b[^c]*c”;
3.3 集合操作死循环(JDK7 HashMap问题)
特征:多线程并发操作HashMap导致链表成环。
解决方案:改用ConcurrentHashMap或使用线程安全的集合类。
3.4 巨型对象序列化
特征:某个对象过大(如包含全表数据的List)被转JSON打印日志。
错误示例:
// 错误示例:打印包含大量数据的对象
log.info(“Data: {}”, hugeList);  // 包含几万条数据
正确示例:
// 正确示例:只打印摘要信息
log.info(“Data size: {}”, hugeList.size());
3.5 MQ消费积压
特征:消息处理逻辑太重,导致消费者线程一直占满CPU。
排查命令:
# 查看所有线程状态
thread
# 查找特定名称的线程
thread | grep ConsumeMessageThread
四、实战案例:电商平台促销期间CPU飙升排查
4.1 问题现象
某电商平台在促销活动期间,监控告警显示核心服务CPU使用率突破95%,接口响应时间从200ms骤增至5秒以上。
4.2 排查步骤
步骤1:快速定位问题线程
# 启动Arthas并连接目标进程
java -jar arthas-boot.jar
# 查看CPU使用率最高的线程
thread -n 3 -i 1000
输出显示有3个名为”AsyncHttpClient-XXX”的线程CPU使用率长期维持在90%以上。
步骤2:分析线程堆栈
# 查看其中一个高CPU线程的堆栈
thread 1897
堆栈显示线程卡在com.core.service.PaymentProcessor.validateCoupon方法。
步骤3:反编译代码确认逻辑
# 反编译PaymentProcessor类
jad com.core.service.PaymentProcessor
发现validateCoupon方法中使用了BigDecimal的divide方法却未指定舍入模式,在某些金额计算时会导致无限循环。
步骤4:生成火焰图确认热点
# 生成60秒的CPU火焰图
profiler start -d 60
profiler stop –format html
火焰图确认validateCoupon方法占用了97%的CPU资源。
4.3 解决方案
修复BigDecimal除法未指定舍入模式的问题:
// 修复前:未指定舍入模式,可能导致无限循环
BigDecimal result = amount.divide(couponValue);
// 修复后:指定舍入模式
BigDecimal result = amount.divide(couponValue, 2, RoundingMode.HALF_UP);
修复后,CPU使用率从95%降至正常水平(20%-30%)。
五、Arthas排查命令速查表
场景
核心命令
关键参数
说明
全局监控
dashboard
-i 3000(刷新间隔)
查看JVM整体状态
定位高CPU线程
thread -n 5
-i 1000(采样时间)
按CPU使用率排序显示线程
查看线程详情
thread <线程ID>
查看指定线程的完整堆栈
反编译类
jad com.xxx.Class
查看线上代码实现
方法追踪
trace com.xxx.method
#cost>100(耗时过滤)
追踪方法内部调用耗时
监控方法
watch com.xxx.method
{params,returnObj}(监控内容)
查看方法入参和返回值
性能分析
profiler start
-d 60(分析时长)
生成CPU火焰图
查看死锁
thread -b
检测死锁线程
方法统计
monitor com.xxx.method
-c 5(统计周期)
统计方法调用次数和耗时
六、最佳实践与注意事项
6.1 安全使用建议
最小权限原则:使用非root账户启动Arthas
sudo -u appuser java -jar arthas-boot.jar
生产环境限制访问:
java -jar arthas-boot.jar –target-ip 0.0.0.0 –telnet-port 3658 –http-port 8563
及时停止:诊断完成后及时退出Arthas,避免长期占用资源
6.2 排查技巧
采样时间设置:使用-i 1000(1秒采样)避免抓到瞬间毛刺
关注业务代码:堆栈顶部的业务代码(通常以com.xxx开头)是排查重点
结合系统工具:Arthas与top、jstack等工具结合使用效果更佳
保留现场证据:在重启服务前保存Arthas诊断结果
6.3 防御性编程建议
循环安全防护:
public void processBatch(BatchTask task) {
    final int MAX_ITERATIONS = 1000000;
    int guardCounter = 0;
    while(task.hasMore()) {
        if (++guardCounter > MAX_ITERATIONS) {
            throw new GuardException(“循环保护触发”);
        }
        // 核心业务逻辑
    }
}
线程池智能监控:
@Bean
public ExecutorService bizExecutor() {
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
        10, 100, 60L, TimeUnit.SECONDS,
        new ResizableCapacityQueue(5000)
    );
    // 监控队列满载触发拒绝
    executor.setRejectedExecutionHandler((task, pool) -> {
        Metrics.counter(“thread.rejected”).increment();
        logger.warn(“线程池过载触发拒绝策略”);
        autoScaleUp(pool);
    });
    return executor;
}
七、总结
使用Arthas排查Java进程CPU飙升问题的核心思路可以总结为三个步骤:
宏观诊断:通过dashboard命令快速判断问题类型(User高、System高还是GC问题)
微观定位:使用thread -n 3 -i 1000定位高CPU线程,通过jad反编译代码确认问题
深度分析:根据需要选择trace、watch或profiler进行方法级分析
根据New Relic发布的《2024全球Java应用性能现状报告》,线上Java应用未预埋诊断组件时,排查平均耗时可达2.7小时,预埋后可压缩至22分钟以内。建议在Java应用启动参数中加入Arthas启动脚本,实现实时诊断能力。
记住,CPU高 ≠ JVM问题,90%是代码问题。通过”找线程 → 看栈 → 定方法 → 改逻辑”的标准流程,结合Arthas的强大功能,大多数CPU飙升问题都能在10分钟内精准定位并解决。
参考资料:
Arthas官方文档
三步搞定CPU飙升!Arthas实战指南
Java服务CPU飙高排查SOP
Arthas进阶实战:Java性能问题3步定位法

购买须知/免责声明
1.本文部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责。
2.若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
3.如果本站有侵犯、不妥之处的资源,请在网站右边客服联系我们。将会第一时间解决!
4.本站所有内容均由互联网收集整理、网友上传,仅供大家参考、学习,不存在任何商业目的与商业用途。
5.本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
6.不保证任何源码框架的完整性。
7.侵权联系邮箱:188773464@qq.com
8.若您最终确认购买,则视为您100%认同并接受以上所述全部内容。

海外源码网 后端编程 使用Arthas排查线上Java进程CPU飙升 https://moyy.us/22129.html

下一篇:

已经没有下一篇了!

相关文章

猜你喜欢