Arthas - monitor 命令,方法执行指标持续监控
👋 大家好,欢迎来到我的技术博客!
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕Arthas这个话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!
文章目录
- Arthas - monitor 命令:方法执行指标持续监控 🚀
- 什么是 Arthas?🧠
- 为什么需要 monitor 命令?🤔
- monitor 命令的核心功能
- monitor 命令的基本语法 🧩
- 准备实验环境:编写示例 Java 应用 💻
- 创建 Maven 项目结构
- 添加依赖(pom.xml)
- 编写 OrderService.java
- 编写 OrderController.java
- 启动类 DemoApplication.java
- 构建并运行应用
- 启动 Arthas 并连接到目标进程 🔗
- 使用 monitor 命令监控 createOrder 方法 🔍
- 更复杂的监控场景:通配符与排除规则 🎯
- 示例:监控所有 service 包下的方法
- 排除特定类
- monitor 的底层原理剖析 🔧
- 字节码增强机制
- 统计维度是如何采集的?
- monitor 与其他命令的对比 🆚
- 实战案例:定位性能劣化问题 🔎
- 问题背景
- 第一步:监控核心方法
- 第二步:使用 trace 分析内部耗时
- 第三步:检查数据库连接池状态
- monitor 的高级技巧与最佳实践 🛠️
- 技巧一:结合 watch 查看失败详情
- 技巧二:限制监控次数避免无限输出
- 技巧三:导出监控数据用于分析
- monitor 的局限性与注意事项 ⚠️
- 1. 不支持构造方法监控
- 2. 无法区分重载方法
- 3. 对性能有一定影响
- 4. 数据精度有限
- 如何在容器化环境中使用 monitor?🐳
- 方式一:进入容器内部执行
- 方式二:挂载 Arthas 到已有镜像
- 方式三:使用 Sidecar 模式
- monitor 在微服务架构中的应用 🌐
- 场景一:逐层排查慢请求
- 场景二:验证限流降级策略
- 场景三:灰度发布期间对比新旧版本
- 总结:让 monitor 成为你的眼睛 👁️
- 延伸阅读 📚
- 致谢 🙏
Arthas - monitor 命令:方法执行指标持续监控 🚀
在现代 Java 应用的运维与性能调优中,我们常常需要对运行中的系统进行实时观测和动态诊断。尤其是在生产环境中,很多问题无法通过日志或传统监控工具直接定位。这时候,一款强大的 Java 诊断工具就显得尤为重要。
而Arthas,正是这样一款由阿里巴巴开源并广泛应用于企业级场景的 Java 诊断利器。它支持在线排查问题、动态查看类信息、监控方法调用、追踪异常堆栈等,无需重启应用,也无需修改代码。
本文将聚焦于 Arthas 中一个非常实用的功能命令 ——monitor,深入讲解其原理、使用方式,并结合实际 Java 代码示例,帮助你掌握如何利用monitor实现方法执行指标的持续监控,从而提升系统的可观测性与稳定性 💡。
什么是 Arthas?🧠
Arthas(阿尔萨斯)是一款开源的 Java 诊断工具,专为开发者和运维人员设计,用于解决线上 Java 程序的问题。它最大的特点是“无需侵入代码、不重启服务、动态增强类行为”,让你像调试本地程序一样观察远程 JVM 的运行状态。
它的核心能力包括:
- 查看已加载类的信息
- 动态反编译类
- 跟踪方法调用链路
- 监控方法执行时间与次数
- 捕获异常抛出点
- 查看线程堆栈、内存占用等 JVM 指标
🔗 官方文档地址:https://arthas.aliyun.com/doc
Arthas 支持多种命令,如trace、watch、stack、tt和我们今天要重点介绍的monitor。每一个命令都针对不同的诊断场景,而monitor正是用于长时间监控某个方法的执行频率与性能表现的理想选择。
为什么需要 monitor 命令?🤔
想象一下这样的场景:
你部署了一个订单处理服务,用户反馈偶尔会出现响应缓慢的情况。但日志里没有明显的错误,Prometheus 或 Grafana 上也没有看到明显的 CPU 高峰。这时你会怀疑是不是某些关键方法执行耗时变长了?
传统的做法可能是添加埋点日志、接入 APM 工具(如 SkyWalking、Pinpoint),但这往往需要提前规划,且有一定的成本和延迟。
而如果你能即时连接到正在运行的 JVM 进程,然后对某个关键方法(比如OrderService.createOrder())进行实时监控,观察它的调用次数、平均耗时、失败率等指标,那岂不是更高效?
这正是monitor命令的价值所在 ✅。
monitor 命令的核心功能
monitor命令可以对匹配的方法进行周期性的统计监控,输出以下关键指标:
| 指标 | 含义 |
|---|---|
timestamp | 统计时间戳 |
class | 类名 |
method | 方法名 |
total | 总调用次数 |
success | 成功次数 |
fail | 失败次数(抛出异常) |
rt | 平均响应时间(毫秒) |
fail-rate | 失败率 |
这些数据每间隔一段时间自动刷新一次(默认120秒),形成一个持续的监控视图,非常适合用来分析方法级别的稳定性与性能趋势。
monitor 命令的基本语法 🧩
monitor-c<interval><class-pattern><method-pattern>参数说明如下:
-c <interval>:统计周期(单位:秒),默认为 120 秒。<class-pattern>:类名通配符表达式,支持*匹配。<method-pattern>:方法名通配符表达式。
例如:
monitor-c30com.example.service.OrderService createOrder表示:每 30 秒统计一次com.example.service.OrderService类中createOrder方法的执行情况。
此外,还可以使用选项来过滤条件:
-m:仅监控被调用的方法(排除构造器)--exclude-class-pattern:排除指定类
⚠️ 注意:
monitor命令基于字节码增强技术实现,会对目标方法进行织入以收集指标。虽然开销极小,但仍建议在必要时使用,避免长期开启影响性能。
准备实验环境:编写示例 Java 应用 💻
为了演示monitor的实际效果,我们先构建一个简单的 Spring Boot 应用,模拟订单创建逻辑,并故意引入一些随机延迟和异常,以便观察监控结果。
创建 Maven 项目结构
假设你的项目名为arthas-monitor-demo,基本目录结构如下:
src/ ├── main/ │ ├── java/ │ │ └── com/example/demo/ │ │ ├── DemoApplication.java │ │ ├── service/OrderService.java │ │ └── controller/OrderController.java │ └── resources/ │ └── application.yml pom.xml添加依赖(pom.xml)
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>arthas-monitor-demo</artifactId><version>1.0.0</version><packaging>jar</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.12</version><relativePath/></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>编写 OrderService.java
packagecom.example.demo.service;importorg.springframework.stereotype.Service;importjava.util.Random;@ServicepublicclassOrderService{privatefinalRandomrandom=newRandom();publicStringcreateOrder(StringuserId,doubleamount)throwsException{// 模拟网络延迟或数据库操作longdelay=50+random.nextInt(200);Thread.sleep(delay);// 10% 概率抛出异常if(random.nextDouble()<0.1){thrownewRuntimeException("Payment failed due to timeout");}return"Order created successfully for user: "+userId+", amount: $"+amount;}publicStringqueryOrder(StringorderId){return"Order status: CONFIRMED, ID="+orderId;}}编写 OrderController.java
packagecom.example.demo.controller;importcom.example.demo.service.OrderService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.*;@RestController@RequestMapping("/api/order")publicclassOrderController{@AutowiredprivateOrderServiceorderService;@PostMapping("/create")publicStringcreateOrder(@RequestParamStringuserId,@RequestParamdoubleamount){try{returnorderService.createOrder(userId,amount);}catch(Exceptione){return"Error: "+e.getMessage();}}@GetMapping("/query")publicStringqueryOrder(@RequestParamStringid){returnorderService.queryOrder(id);}}启动类 DemoApplication.java
packagecom.example.demo;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublicclassDemoApplication{publicstaticvoidmain(String[]args){SpringApplication.run(DemoApplication.class,args);}}构建并运行应用
使用 Maven 打包并运行:
mvn clean packagejava-jartarget/arthas-monitor-demo-1.0.0.jar启动成功后,你可以通过以下命令测试接口是否正常工作:
curl"http://localhost:8080/api/order/create?userId=u123&amount=99.9"多次执行该命令,会发现大约每十次就有一次返回错误,符合我们的预期逻辑 ✅。
启动 Arthas 并连接到目标进程 🔗
接下来,我们需要下载并启动 Arthas,将其 attach 到刚才运行的 Java 进程上。
🔗 下载地址:https://arthas.aliyun.com/doc/download.html
根据官方指引,推荐使用一键安装脚本(适用于 Linux/macOS):
curl-Ohttps://arthas.aliyun.com/arthas-boot.jarjava-jararthas-boot.jar运行后,控制台会列出当前机器上所有可用的 Java 进程:
[1]: 12345 demo.ArthasApplication [2]: 67890 org.apache.catalina.startup.Bootstrap输入对应进程编号(比如1),回车即可连接成功。
连接成功后你会看到类似提示:
Arthas server already started!此时你已经进入了 Arthas 的交互式命令行界面,可以开始输入各种诊断命令了!
使用 monitor 命令监控 createOrder 方法 🔍
现在我们正式进入主题:使用monitor命令监控OrderService.createOrder方法的执行指标。
输入以下命令:
monitor-c10com.example.demo.service.OrderService createOrder解释:
-c 10表示每 10 秒输出一次统计数据com.example.demo.service.OrderService是完整类名createOrder是要监控的方法名
执行后,Arthas 将开始周期性地打印监控结果,类似如下内容:
timestamp class method total success fail rt fail-rate 2025-04-05 10:23:00 com.example.demo.service.OrderService createOrder 5 4 1 120 20.0% 2025-04-05 10:23:10 com.example.demo.service.OrderService createOrder 8 7 1 115 12.5% 2025-04-05 10:23:20 com.example.demo.service.OrderService createOrder 6 6 0 108 0.0%从上面的数据可以看出:
- 第一个周期内共调用了 5 次,失败 1 次,平均耗时 120ms
- 第二个周期调用 8 次,失败 1 次,平均耗时下降至 115ms
- 第三个周期全部成功,响应更快
这说明我们的服务整体稳定,偶发失败也得到了体现,完全符合代码逻辑 👏。
更复杂的监控场景:通配符与排除规则 🎯
有时候我们不想只监控单个方法,而是希望批量监控某一组方法。这时可以借助通配符*来实现。
示例:监控所有 service 包下的方法
monitor-c30*service*.create* *这条命令将匹配所有包含service和create的类及其任意方法。
不过要注意,这种宽泛的匹配可能会带来大量无关方法的监控,增加系统负担。因此建议尽量精确匹配。
排除特定类
假设你想监控所有OrderService的方法,但不想包括queryOrder,可以这样做:
monitor-c15com.example.demo.service.OrderService * --exclude-method-pattern queryOrder❗ 注意:目前 Arthas 的
monitor命令暂不支持--exclude-method-pattern参数,但我们可以通过组合其他命令(如trace)间接实现类似功能。这是未来版本可能优化的方向。
monitor 的底层原理剖析 🔧
要真正理解monitor的强大之处,我们必须了解它是如何工作的。
字节码增强机制
Arthas 使用了 Java 的Instrumentation API和ASM 字节码操作库,在 JVM 运行时动态修改类的字节码,向目标方法中插入统计逻辑。
具体流程如下:
这个过程是无侵入的,原始.class文件不会被修改,所有的变更仅存在于内存中。一旦退出 Arthas 或 JVM 关闭,增强就会失效。
统计维度是如何采集的?
当monitor生效后,Arthas 会在每个目标方法前后织入类似以下伪代码的逻辑:
longstart=System.nanoTime();try{// 原始方法逻辑originalMethod.invoke();successCount++;}catch(Throwablet){failCount++;throwt;}finally{totalTime+=(System.nanoTime()-start)/1_000_000;// mstotalCount++;}这些计数器保存在一个全局映射表中,由后台线程定时读取并格式化输出。
由于所有操作都在 JVM 内部完成,几乎没有网络开销,因此响应非常迅速 ⚡。
monitor 与其他命令的对比 🆚
Arthas 提供了多个用于方法监控的命令,它们各有侧重。下面我们做一个横向对比:
| 命令 | 用途 | 是否持续 | 精度 | 典型场景 |
|---|---|---|---|---|
monitor | 周期性统计调用次数、RT、失败率 | ✅ 是 | 中 | 长期观察方法稳定性 |
watch | 观察方法入参、返回值、异常 | ✅ 可持续 | 高 | 调试参数传递问题 |
trace | 跟踪方法内部调用链及耗时分布 | ❌ 单次 | 极高 | 分析性能瓶颈 |
stack | 输出方法被调用时的堆栈 | ❌ 单次 | 高 | 查找调用来源 |
tt(Time Tunnel) | 记录方法调用快照,支持重放 | ✅ 可录制 | 高 | 复杂问题复现 |
可以看到,monitor的优势在于轻量、持续、适合宏观监控,而其他命令更适合做微观分析。
举个例子:
- 你想知道
createOrder最近一分钟失败了多少次?→ 用monitor - 你想看某次失败调用传入了什么参数?→ 用
watch - 你想找出
createOrder里哪个子方法最慢?→ 用trace
合理搭配使用,才能发挥最大威力 💪。
实战案例:定位性能劣化问题 🔎
让我们来看一个真实的故障排查场景。
问题背景
某电商平台在大促期间发现下单接口响应明显变慢,但日志未见异常。运维团队怀疑是数据库连接池耗尽或缓存失效导致。
此时,我们可以立即使用 Arthas 的monitor命令介入分析。
第一步:监控核心方法
连接到订单服务进程后,执行:
monitor-c10com.example.trade.service.TradeService placeOrder观察输出:
timestamp class method total success fail rt fail-rate 2025-04-05 14:00:00 TradeService placeOrder 120 118 2 850 1.7% 2025-04-05 14:00:10 TradeService placeOrder 135 132 3 920 2.2% 2025-04-05 14:00:20 TradeService placeOrder 140 130 10 1400 7.1% 2025-04-05 14:00:30 TradeService placeOrder 130 110 20 2100 15.4%发现问题:
- RT 从 850ms 持续上升到 2100ms,翻了一倍多!
- 失败率也在快速攀升,已达 15%
初步判断:系统出现性能雪崩,需进一步定位瓶颈。
第二步:使用 trace 分析内部耗时
切换到trace命令查看方法内部调用树:
trace com.example.trade.service.TradeService placeOrder输出片段:
`---ts=2025-04-05 14:01:00;thread_name=http-nio-8080-exec-7;id=2a;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader `---[1567.238592ms] com.example.trade.service.TradeService:placeOrder() +---[0.123ms] com.example.trade.validator.OrderValidator:validate() +---[23.456ms] com.example.trade.generator.OrderIdGenerator:generate() +---[1500.123ms] com.example.trade.dao.OrderDao:saveToDatabase() `---[43.536ms] com.example.trade.mq.Producer:sendConfirmMessage()清晰可见,saveToDatabase耗时高达1.5秒,是主要瓶颈!
第三步:检查数据库连接池状态
结合 Spring Boot Actuator 的/actuator/metrics/hikaricp.connections.active接口,发现活跃连接数已达最大值 20,说明连接池被打满。
最终结论:数据库连接泄漏导致后续请求排队等待,引发连锁反应 ❗。
解决方案:
- 增加连接池大小(临时缓解)
- 检查 DAO 层是否有未关闭的 Connection(根本解决)
整个排查过程不到 10 分钟,充分体现了monitor + trace组合拳的强大战斗力 🥊。
monitor 的高级技巧与最佳实践 🛠️
掌握了基础用法之后,我们来看看一些进阶技巧,帮助你在复杂场景下更高效地使用monitor。
技巧一:结合 watch 查看失败详情
虽然monitor能告诉你失败了多少次,但它不会告诉你为什么会失败。这时可以配合watch命令捕获异常信息:
watchcom.example.demo.service.OrderService createOrder'{params, throwExp}'-e-e表示只监听抛出异常的情况{params, throwExp}输出参数和异常对象
输出示例:
params=[u123, 99.9], throwExp=java.lang.RuntimeException: Payment failed due to timeout这样就能精准定位到是支付超时导致失败,便于后续优化。
技巧二:限制监控次数避免无限输出
默认情况下,monitor会一直输出直到手动中断(Ctrl+C)。但在自动化脚本中,我们可能只想采集 N 个周期的数据。
虽然monitor本身不支持--number参数(不像trace),但我们可以通过 shell 控制:
# 只采集 3 次,每次间隔 10 秒foriin{1..3};dojava-jararthas-boot.jar--exec"monitor -c 10 com.example.service.OrderService createOrder"|head-n5sleep10done🔗 更多 Shell 脚本技巧参考:https://www.gnu.org/software/bash/manual
技巧三:导出监控数据用于分析
你可以将monitor输出重定向到文件,供后续分析:
java-jararthas-boot.jar--exec"monitor -c 60 com.example.service.* *">monitor.log然后使用 Python 或 Excel 对rt和fail-rate进行可视化分析,绘制趋势图。
例如用 Pandas 读取日志并绘图:
importpandasaspdimportmatplotlib.pyplotasplt df=pd.read_csv('monitor.log',sep='\s+',skiprows=1)df['timestamp']=pd.to_datetime(df['timestamp'])df.set_index('timestamp').plot(y='rt',kind='line')plt.title('Average Response Time Trend')plt.ylabel('RT (ms)')plt.show()monitor 的局限性与注意事项 ⚠️
尽管monitor功能强大,但也有一些限制需要注意:
1. 不支持构造方法监控
monitor默认不监控构造函数(constructor),即使你写了monitor java.util.ArrayList <init>也不会生效。
如果确实需要监控构造器,建议改用trace或watch。
2. 无法区分重载方法
当你有多个同名但参数不同的方法时,monitor会同时监控所有重载版本,无法单独指定某个签名。
例如:
voidprocess(Strings)voidprocess(inti)执行monitor com.example.Utils process会同时监控两个方法。
若需区分,可使用trace配合条件表达式:
trace com.example.Utils process'params[0].getClass().getName()=="java.lang.String"'3. 对性能有一定影响
虽然 Arthas 的增强非常轻量,但每调用一次方法都要执行额外的计数逻辑,在高并发场景下仍可能带来微小延迟。
建议:
- 仅在排查问题时启用
- 避免监控高频调用的方法(如 getter/setter)
- 使用较短的监控周期(如 10~30 秒)
4. 数据精度有限
monitor提供的是周期性聚合数据,无法还原每一次调用的详细信息。如果你需要精确到每次调用的时间戳、参数、返回值,则应使用tt或watch。
如何在容器化环境中使用 monitor?🐳
随着 Kubernetes 和 Docker 的普及,越来越多的应用运行在容器中。那么,我们还能使用 Arthas 吗?
答案是:完全可以!
方式一:进入容器内部执行
假设你的 Pod 名称为order-service-7d5b8c9f4-xz2lw,可以这样做:
# 进入容器kubectlexec-itorder-service-7d5b8c9f4-xz2lw -- /bin/sh# 安装 Arthas(前提是有网络)curl-Ohttps://arthas.aliyun.com/arthas-boot.jarjava-jararthas-boot.jar⚠️ 注意:容器内需安装 JDK 和基础工具(如 curl、ps)
方式二:挂载 Arthas 到已有镜像
推荐做法是在构建镜像时预装 Arthas:
FROM openjdk:8-jdk-alpine COPY arthas-boot.jar /opt/arthas/ COPY app.jar /app.jar CMD ["java", "-jar", "/app.jar"]启动后可通过kubectl exec进入并运行:
java-jar/opt/arthas/arthas-boot.jar方式三:使用 Sidecar 模式
在 Kubernetes 中部署一个独立的诊断容器,共享同一个 Network Namespace,实现跨容器诊断。
这种方式更加安全,避免污染主应用容器。
🔗 更多 Kubernetes 调试技巧参考:https://kubernetes.io/docs/tasks/debug-application-cluster/debug-running-pod/
monitor 在微服务架构中的应用 🌐
在微服务架构中,单个请求往往会跨越多个服务节点。此时,单一服务的monitor数据只是冰山一角。
但我们仍然可以用它来做很多事情:
场景一:逐层排查慢请求
假设用户投诉“下单太慢”,我们可以:
- 在 API Gateway 层
monitor入口方法 - 在订单服务
monitorcreateOrder - 在库存服务
monitordeductStock - 在支付服务
monitorpay
通过对比各环节的 RT,快速定位瓶颈所在。
场景二:验证限流降级策略
当我们上线了新的熔断规则后,可以用monitor验证是否生效:
monitor-c5com.example.service.PaymentService pay故意发起大量请求,观察fail数是否随时间上升,rt是否因拒绝而降低。
如果是,则说明限流生效;否则需要检查配置。
场景三:灰度发布期间对比新旧版本
在灰度发布时,可以在新旧两个实例上分别运行相同的monitor命令,比较性能差异:
| 版本 | avg RT | max fail-rate |
|---|---|---|
| v1.0 | 120ms | 1.2% |
| v1.1 | 98ms | 0.5% |
数据证明新版本更优,方可全量发布 ✅。
总结:让 monitor 成为你的眼睛 👁️
monitor命令虽小,却蕴含巨大能量。它就像一双始终盯着你关键方法的眼睛,默默记录着每一次调用的命运 —— 成功或失败,快速或迟缓。
在本文中,我们从零开始搭建环境,编写 Java 示例代码,演示了如何使用monitor进行持续监控,并深入探讨了其原理、适用场景、实战技巧以及在现代架构中的应用。
记住:
✅ 当你需要长期观察方法稳定性时,选
monitor
✅ 当你需要深入分析单次调用细节时,选watch或trace
✅ 当你需要全面掌控系统健康状况时,请把它们结合起来使用!
Arthas 不仅是一个工具,更是一种思维方式 ——主动观测、即时响应、数据驱动决策。
愿你在未来的线上问题面前,不再手足无措,而是从容打开终端,输入一行monitor,静静等待真相浮现 🌟。
延伸阅读 📚
- Arthas 官方文档 —— 获取最新命令手册与使用指南
- Java Instrumentation API 文档 —— 深入理解字节码增强机制
- OpenTelemetry vs Arthas:谁更适合生产诊断? —— 对比传统 APM 与动态诊断工具
- 阿里巴巴中间件团队博客 —— 学习更多 Arthas 实战经验分享
致谢 🙏
感谢 Arthas 开源团队为我们提供了如此强大的诊断工具,也感谢每一位在生产一线坚守的开发者与运维工程师。正是因为你们的努力,才让这个世界运转得更加平稳流畅。
Keep calm and use Arthas. 😎
🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍点赞、📌收藏、📤分享给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨
