线上环境无法进行传统意义上的断点调试,这无疑是许多Java开发者在排查问题时的一大痛点。当遇到某个方法执行缓慢,或者想了解其调用频率、成功率等实时指标时,如果不能侵入式地修改代码、发布重启,我们该怎么办?
Arthas,作为阿里巴巴开源的Java诊断工具,正是为解决这类问题而生。它以非侵入式的方式,在不重启JVM的情况下,提供了强大的运行时诊断能力。下面我们就来详细探讨,如何利用Arthas查看某个方法的实时调用情况,并分析其性能瓶颈。
Arthas简介
Arthas是一款Java应用线上诊断工具,当应用部署在生产环境出现问题时,Arthas可以帮助我们快速定位并解决问题。它支持对运行中的JVM进行热插拔,提供诸如查看JVM信息、线程信息、类加载信息、方法调用链路、性能指标等功能,是线上问题排查的利器。
第一步:连接到目标JVM进程
在使用Arthas之前,首先需要将它attach到你的Java应用进程上。
下载Arthas:
curl -O https://arthas.aliyun.com/arthas-boot.jar启动Arthas:
java -jar arthas-boot.jar执行后,Arthas会列出当前机器上运行的Java进程,让你选择要attach的进程ID。输入对应的PID,回车即可连接。
* [1]: 12345 your-application.jar * [2]: 67890 another-application.jar ... Please choose a Java process to attach, input index[1,2]:选择你的应用进程ID后,你就进入了Arthas控制台。
第二步:监控方法的实时调用情况
针对“查看某个方法的实时调用情况”和“分析性能瓶颈”的需求,Arthas提供了monitor和trace等核心命令。
1. 使用 monitor 命令监控方法统计信息
monitor 命令用于监控指定方法的执行统计信息,包括调用次数、成功失败次数、平均响应时间(RT)、QPS(每秒查询数)等。这对于快速了解一个方法的整体健康状况和性能表现非常有用。
命令格式:monitor -c [统计周期] [类全限定名] [方法名]
示例: 假设我们有一个com.example.service.UserService类,其中有一个getUserById方法,我们想每隔5秒监控一次它的调用情况。
monitor -c 5 com.example.service.UserService getUserById
输出示例解析:
Press Ctrl+C to abort.
Time Total Success Fail RT(ms) QPS Failed(%)
--------------------------------------------------------------------------
2023-10-27 10:00:05 100 95 5 12.5 20 5.00
2023-10-27 10:00:10 120 118 2 10.2 24 1.67
...
Time: 统计时间点。Total: 总调用次数。Success: 成功次数。Fail: 失败次数。RT(ms): 平均响应时间(毫秒)。QPS: 每秒查询数。Failed(%): 失败率。
通过monitor,你可以直观地看到方法的调用频率是否异常、响应时间是否过长,以及是否有大量失败,从而快速定位到可能存在问题的服务或方法。
2. 使用 trace 命令追踪方法内部调用路径及耗时
当monitor发现某个方法的RT过高时,我们可能需要进一步了解这个方法内部是哪一步耗时较长,这时trace命令就派上用场了。trace可以追踪方法执行的整个路径,并记录每个子方法调用的耗时。
命令格式:trace [类全限定名] [方法名] [条件表达式] -n [调用次数]
示例: 继续上面的例子,我们怀疑getUserById内部有耗时操作,想追踪它。
trace com.example.service.UserService getUserById
或者,如果只想追踪前5次调用:
trace com.example.service.UserService getUserById -n 5
如果方法参数或返回值较大,或者需要过滤特定调用,还可以结合watch命令进行更详细的观察,或者使用条件表达式。
输出示例解析:
`---ts=2023-10-27 10:05:01; [cost=15.341ms] thread=main`
`---[com.example.service.UserService:getUserById()]`
`---[com.example.dao.UserDAO:selectById() cost=10.210ms]`
`---[com.example.cache.UserCache:put() cost=2.150ms]`
`---[com.example.util.DataConverter:convert() cost=0.500ms]`
cost: 表示当前方法或子方法从开始到结束的执行总耗时。- 输出会以树形结构展示方法的调用链路,每个子方法前会显示其自身的耗时。
- 通过观察
cost值,可以清晰地看到getUserById方法中,selectById()耗时最长,这可能就是性能瓶颈所在。
过滤条件 (-E 或 SpEL表达式):
当你只想追踪满足特定条件的方法调用时,可以使用条件表达式。例如,只追踪用户ID为100的调用:
trace com.example.service.UserService getUserById "params[0]==100"
这里params[0]表示第一个方法参数。
第三步:停止Arthas命令
当完成诊断后,可以通过Ctrl+C停止当前正在执行的命令(如monitor、trace)。
如果想退出Arthas控制台,可以使用quit或exit命令。
总结
Arthas提供了一种强大的非侵入式方式来诊断线上Java应用。
monitor让你能从宏观层面了解方法的调用统计信息,快速发现异常的QPS、RT或失败率。trace则深入到微观层面,帮你剖析方法内部的调用链和各环节的耗时,精确锁定性能瓶颈。
结合这两个命令,你可以高效地在不影响线上服务的前提下,进行实时的性能分析和问题排查。掌握Arthas,无疑会大大提升你在生产环境下的问题解决能力。