Arthas十大高频使用场景实录

实战经验总结,带你玩转Java诊断利器

作为阿里开源的Java诊断工具,Arthas已经成为开发者排查线上问题的利器。它通过简单的命令行交互,提供了强劲的监控和诊断功能。今天,我将通过真实案例带你领略Arthas最常用的十大场景。

场景一:快速定位方法执行问题

问题场景:用户反馈某个功能响应缓慢,但日志没有明显错误。

解决步骤

# 启动Arthas
./as.sh --target-ip 127.0.0.1 -c "12345"

# 监控方法执行耗时
[arthas@12345]$ watch com.example.UserService queryUserInfo '{params, returnObj, #cost}'

执行结果

method=com.example.UserService.queryUserInfo location=AtExit
ts=2023-10-01 10:30:00; [cost=1568.228ms] result=@ArrayList[
    @Object[][
        @String[1001],
    ],
    @UserInfo[UserInfo{userId=1001, userName="张三"}],
]

分析:发现该方法执行耗时1.5秒,明显异常。进一步排查发现是数据库连接池问题。

场景二:动态追踪方法调用路径

问题场景:某个方法被多次调用,但不确定调用来源。

# 追踪方法调用栈
[arthas@12345]$ trace com.example.OrderService createOrder '#cost > 500'

执行结果

`---ts=2023-10-01 10:35:00;thread_name=http-nio-8080-exec-1;id=1e;is_daemon=true;priority=5;TCCL=org.springframework.boot.loader.LaunchedURLClassLoader
    `---[1568.228ms] com.example.OrderService:createOrder()
        +---[1.228ms] com.example.OrderService:validateParams() #12
        +---[1565.228ms] com.example.OrderService:saveToDB() #15
        `---[1.772ms] com.example.OrderService:sendNotification() #18

发现:saveToDB方法耗时占比99%,是性能瓶颈所在。

场景三:实时监控方法入参和返回值

问题场景:需要观察某个关键方法的输入输出数据。

# 监控方法入参和返回值
[arthas@12345]$ watch com.example.PaymentService processPayment '{params, returnObj, throwExp}' -x 3

执行结果

method=com.example.PaymentService.processPayment location=AtExit
ts=2023-10-01 11:00:00; result=@ArrayList[
    @Object[][
        @PaymentRequest[PaymentRequest{orderId=2001, amount=999.00, paymentType="ALIPAY"}],
    ],
    @PaymentResult[PaymentResult{success=true, transactionId="TXN202310011100001"}],
    null,
]

场景四:热更新代码修复线上Bug

问题场景:发现线上空指针异常,需要紧急修复但不想重启服务。

步骤

# 1. 反编译当前类
[arthas@12345]$ jad --source-only com.example.UserService > /tmp/UserService.java

# 2. 修改代码(添加空指针判断)
# 原代码:
# public UserInfo getUserById(String userId) {
#     return userMap.get(userId);
# }

# 修改后:
public UserInfo getUserById(String userId) {
    if (userId == null) {
        return null;
    }
    return userMap.get(userId);
}

# 3. 编译修改后的类
[arthas@12345]$ mc -c 12345 /tmp/UserService.java -d /tmp

# 4. 热更新类
[arthas@12345]$ retransform /tmp/com/example/UserService.class

场景五:监控系统异常和错误

问题场景:系统偶尔抛出异常,但日志没有完整记录。

# 监控特定异常
[arthas@12345]$ watch *Exception getMessage -e

执行结果

method=java.lang.NullPointerException.getMessage location=AtExit
ts=2023-10-01 11:30:00; result=null
method=java.sql.SQLException.getMessage location=AtExit  
ts=2023-10-01 11:31:00; result="Connection timeout"

场景六:分析方法调用统计

问题场景:需要了解某个方法的调用频率和成功率。

# 方法调用监控
[arthas@12345]$ monitor -c 5 com.example.OrderService createOrder

执行结果

 timestamp            class                                           method    total  success  fail  avg-rt(ms)
 2023-10-01 11:40:00  com.example.OrderService                        createOrder  120     115      5     345.2
 2023-10-01 11:40:05  com.example.OrderService                        createOrder  135     128      7     328.7

场景七:线程池问题诊断

问题场景:应用响应变慢,怀疑线程池阻塞。

# 查看线程堆栈
[arthas@12345]$ thread

# 查看阻塞线程
[arthas@12345]$ thread -b

执行结果

"http-nio-8080-exec-5" Id=25 BLOCKED on java.util.concurrent.FutureTask@1a2b3c4d
    at com.example.ReportService.generateReport(ReportService.java:45)
    -  blocked on java.util.concurrent.FutureTask@1a2b3c4d
    at java.util.concurrent.FutureTask.get(FutureTask.java:205)

场景八:动态修改日志级别

问题场景:生产环境需要临时开启DEBUG日志排查问题。

# 查看当前日志级别
[arthas@12345]$ logger --name com.example --include-no-appender

# 修改日志级别
[arthas@12345]$ logger --name com.example --level debug

执行结果

name        ROOT
class       ch.qos.logback.classic.Logger
level       INFO
additivity  true

... updating to DEBUG

场景九:内存泄漏排查

问题场景:应用内存持续增长,怀疑内存泄漏。

# 查看堆内存对象统计
[arthas@12345]$ heapdump --live /tmp/heapdump.hprof

# 查看对象实例数量
[arthas@12345]$ ognl '@java.lang.System@gc()'
[arthas@12345]$ memory

场景十:性能瓶颈分析

问题场景:CPU使用率持续高位运行。

# 生成火焰图分析CPU使用
[arthas@12345]$ profiler start
[arthas@12345]$ profiler stop --format html

# 查看最繁忙的线程
[arthas@12345]$ thread -n 3 -i 1000

执行结果

"Catalina-exec-1" Id=23 cpuUsage=85%
    at java.lang.Thread.sleep(Native Method)
    at com.example.ReportService.calculateData(ReportService.java:123)
    
"Catalina-exec-2" Id=24 cpuUsage=78%
    at java.util.Arrays.sort(Arrays.java:1438)
    at com.example.DataService.sortData(DataService.java:456)

实用技巧:批量操作脚本

对于复杂的诊断场景,可以编写Arthas脚本:

# diagnosis.txt
watch com.example.UserService getUserById '{params, returnObj, #cost}' -x 2
trace com.example.OrderService * '#cost > 1000'
monitor -c 10 com.example.PaymentService *

# 执行脚本
[arthas@12345]$ batch -f diagnosis.txt

总结

Arthas的强劲之处在于它能够在生产环境无侵入地进行诊断。通过这十大高频场景,我们可以看到:

  1. 快速定位:无需重启应用,实时发现问题
  2. 深度分析:从方法级别到系统级别的全面监控
  3. 即时修复:热更新能力让线上问题快速解决
  4. 性能优化:精准定位性能瓶颈

掌握这些场景,你就能从容应对大部分Java应用线上问题。记住,好的工具要用在刀刃上,Arthas就是你排查线上问题的”瑞士军刀”!

温馨提示:生产环境使用Arthas时,提议在业务低峰期操作,避免对正常业务造成影响。

© 版权声明

相关文章

8 条评论

none
暂无评论...