基于arthas量化监控诊断java应用方法论与实践

写在文章开头

应用系统监控也是软件研发中最重要的一环,从研发的角度来说,明确指出自己业务维度明确指出个人负责功能业务维度的系统监控指标,同时具备实时监控诊断的应对方法,是软件架构成功的重要的一环。所以本文将针对故障和监控两个重要概念展开探讨,同时给出一种理想化的架构结合实践案例基于参考,希望对你有所帮助。

我是 SharkChili ,Java 开发者,Java Guide 开源项目维护者。欢迎关注我的公众号:写代码的SharkChili ,也欢迎您了解我的开源项目 mini-redis:github.com/shark-ctrl/...

为方便与读者交流,现已创建读者群。关注下方公众号获取我的联系方式,添加时备注加群即可加入。

浅谈监控的基本概念

故障的生命周期

故障的生命周期分为以下几个阶段:

  1. 故障开始
  2. 故障发现
  3. 故障定位
  4. 及时修复
  5. 系统恢复

这其中,故障发现和通知在市面上已经有一套相对成熟的体系参考,无论是运维还是研发总会有一套自己系统监控的理论,并在应用中完成运用实现监控和告警。 那么问题来了,从研发的角度,针对系统监控各项性能指标,如何明确定位到具体的错误?例如:

  1. 系统提示CPU飙升,面对宏观的性能指标,我们如何知晓故障线程?
  2. web请求全体夯死,系统监控全面告知线程处于wating状态,我们如何定位到问题的根因并优化?
  3. 程序堆内存飙升达到与之,我们如何定位到进程级别的具体问题对象从而定位到问题的栈帧?

如下图,这就是笔者面板中最常见的容器线程直线飙升导致大量请求夯死超时,按照现有体系中的grafana监控面板,面对成百上千的接口请求,即时我们能够准确的做到故障发现,也无法非常快速精准的做到故障定位:

缺少精准的定位动作,就看导致止损动作对故障恢复没有任何帮助,就需要进行重新定位,进而导致负责人员花费大量时间在故障发现和止损动作之间循环往复的执行。

笔者理想中的监控体系

监控是可以确保提前暴露被即时发现解决,同时也可以作为日常循环后系统调优的佐证。所以量化一切监控体系之后,我们就需要搭建一个完善、安全、成熟的监控诊断体系来排查定位问题, 以笔者研发的java应用为例,主流的应用监控会通过micrometer采集目标监控指标,并将其同步到prometheus并通过grafana进行增强渲染,在此基础之上通过Nightingale针对这些告急的监控及时下发企微消息或者短信告警让研发人员介入解决问题:

按照笔者上面的说法,这种做法存在如下几个问题:

  1. 市面仅仅指定常见系统级别监控指标,粒度在如今的应用系统中显得过于宽泛
  2. 团队指定指标往往会因为各种原因无法精准、明确,可快速定位检索各种异常和监控故障的应用级别监控指标
  3. grafanaNightingale是面向于运维和研发的通用,且着重于监控可视化和阈值告警,并不能很好的做到监控诊断。

所以,在此基础之上笔者也给出了一套基于自己常见的工具所衍生了一套带有监控诊断的监控运维体系架构,即在上述监控体系下集成强阿里系中强大的监控诊断工具arthas

如下图,在这套监控体系下,通过arthas tunel远程统一管理所有被arthas agent代理的java应用程序,当其他监控运维工具感知异常时,我们就可以快速通过浏览器attach到存在故障的进程中,以超细粒度灵活的指令和表达式定位java程序中对象内存占用、CPU利用率甚至是栈帧的调用细节:

基于arhtas的应用远程监控实践

arthas监控诊断体系说明

基于上述的说明,我们大体了解的监控诊断的一套理想架构,而本文将针对该架构进行演示和实践,按照arthas官网的说明,对于spring boot项目,我们在项目中引入arthas-spring-boot-starter,其底层会启动一个arthas进程并attach到装配的应用上,由此构建出当前服务的arthas agent

这一点,我们可以通过ArthasConfigurationarthasAgent这个bean得以印证,可以看到它会拉取spring boot配置后,通过这个配置构建arthasAgent并调用init完成如下工作:

  1. 通过Instrumentation注册字节码转换器即ClassFileTransformer,后续通过该技术实现类加载或者运行时字节码动态增强
  2. 拉取一个artahs agentattach到当前进程构成artahs服务端,监听客户端指令完成目标类增强:

对应笔者也给出这段源码的视线入口,读者可以自行参阅:

less 复制代码
@ConditionalOnMissingBean
 @Bean
 public ArthasAgent arthasAgent(@Autowired Map<String, String> arthasConfigMap,
   @Autowired ArthasProperties arthasProperties) throws Throwable {
  arthasConfigMap = StringUtils.removeDashKey(arthasConfigMap);
  // 给配置全加上前缀
  Map<String, String> mapWithPrefix = new HashMap<String, String>(arthasConfigMap.size());
  for (Entry<String, String> entry : arthasConfigMap.entrySet()) {
   mapWithPrefix.put("arthas." + entry.getKey(), entry.getValue());
  }
  //基于配置完成构建artahs agent,完成arthas agent服务端初始化,监听客户端指令完成字节码增强
  
  final ArthasAgent arthasAgent = new ArthasAgent(mapWithPrefix, arthasProperties.getHome(),
    arthasProperties.isSlientInit(), null);

  arthasAgent.init();
  logger.info("Arthas agent start success.");
  return arthasAgent;

 }

同时,考虑到当前应用体系下成百个服务,我们需要有一个统一的入口集中化监控管理,所以为了能够有一个统一的入口集中管理所有的agent,我们会专门用一台与外界隔离的服务器部署一个Arthas Tunnel,让所有的应用程序生成agent后统一与tunel建立连接,后续我们就可以通过tunel暴露的端口,统一管理监控诊断存在异常风险的应用程序:

项目中集成arthas

对于需要arthas agent的程序,我们首先需要引入arthas 脚手架依赖包:

xml 复制代码
 <dependency>
   <groupId>com.taobao.arthas</groupId>
   <artifactId>arthas-spring-boot-starter</artifactId>
   <version>3.4.1</version>
  </dependency>

然后配置agent唯一id并指定tunel的注册地址(默认暴露端口为7777):

ini 复制代码
arthas.agent-id=hsehdfsfghhwertyfad
arthas.tunnel-server=ws://127.0.0.1:7777/ws

随后我们到官网下载并启动tunel

vbscript 复制代码
java -jar arthas-tunnel-server-4.1.2-fatjar.jar

此时我们就可以启动我们的java程序了,控制台出现如下提示,则说明服务启动并成功注册到arthas了:

ini 复制代码
2025-12-07 22:09:21.370  INFO 68696 --- [           main] c.a.arthas.spring.ArthasConfiguration    : Arthas agent start success.
2025-12-07 22:09:21.483  INFO 68696 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 18080 (http)

此时键入http://127.0.0.1:8080/即可进入tunel面板,键入刚刚的agentid即可直接进入监控面板:

这里补充说明一下感兴趣的读者可以到官网拉取arhtas的源码包,以笔者为例这里选择arhtas-all-3.6.0版本,并在配置文件中关闭redis监控,避免本机没有redis服务端连接导致自动装配阶段报错:

ini 复制代码
management.health.redis.enabled=false

通过运行ArthasTunnelApplicationtunel启动:

arthas tunel系统架构监控实践

回到最早的问题,面对大量飙升处于wating状态的线程因为监控工具和指标的局限性而发做到快速的监控诊断,有了arthas监控诊断体系架构,笔者用下面这样的一个接口模拟一个存在问题的分页查询并演示一下快速的解决步骤:

typescript 复制代码
 @GetMapping("/slow-request")
    public JSONObject handleUserPageQuery() {
        // 调用service的用户分页列表查询方法
        return userService.getUserPageList();
    }

查看UserServicegetUserPageList,可以看到其内部用休眠模拟分页查询的长耗时:

typescript 复制代码
public JSONObject getUserPageList() {
        log.info("开始查询用户分页列表");
        
        // 模拟耗时的用户分页列表查询,休眠1分钟
        ThreadUtil.sleep(1, TimeUnit.DAYS);
        
        // 构造分页列表结果
        JSONObject result = new JSONObject();
        result.set("code", 200);
        result.set("message", "success");
        JSONObject data = new JSONObject();
        data.set("total", 100);
        data.set("pageSize", 10);
        data.set("currentPage", 1);
        // 模拟用户列表数据
        JSONObject user1 = new JSONObject();
        user1.set("id", 1);
        user1.set("name", "张三");
        user1.set("email", "zhangsan@example.com");
        
        JSONObject user2 = new JSONObject();
        user2.set("id", 2);
        user2.set("name", "李四");
        user2.set("email", "lisi@example.com");
        
        data.set("users", new JSONObject[]{user1, user2});
        result.set("data", data);
        
        log.info("用户分页列表查询完成");
        return result;
    }

通过上文的tunel入口,我们很快的进入到程序内部,简单快速的定位的tomcat那些存在time wating的问题线程:

非常简单干脆的定位到了问题线程的栈帧,很好的完成监控体系中的监控诊断这一步:

小结

笔者认为,一个健壮的系统运维监控体系是着重于强调量化且可感知观测的,在日常工作的对接中,我发现大量研发人员都有一种计算机文科化的趋势,小到应用程序指标调测,达到故障定位暴力迭代结合日志盲目推测。 结合这些问题,笔者通过这篇文章给出一个理想的监控体系,也希望对读者有所启发。

我是 SharkChili ,Java 开发者,Java Guide 开源项目维护者。欢迎关注我的公众号:写代码的SharkChili ,也欢迎您了解我的开源项目 mini-redis:github.com/shark-ctrl/...

为方便与读者交流,现已创建读者群。关注下方公众号获取我的联系方式,添加时备注加群即可加入。

我是 SharkChili ,Java 开发者,Java Guide 开源项目维护者。欢迎关注我的公众号:写代码的SharkChili,也欢迎您了解我的开源项目 mini-redis:github.com/shark-ctrl/...

为方便与读者交流,现已创建读者群。关注上方公众号获取我的联系方式,添加时备注加群即可加入。

参考

阿里Arthas深度详解:从底层原理到生产实战,Java问题排查不再愁:blog.csdn.net/jam_yin/art...

项目启动报错:Redis health check failed:www.cnblogs.com/yl97/p/1492...

Tunnel Server:www.xiehai.zone/arthas/inst...

《运维监控系统实战笔记》

实战开发 arthas-spring-boot-starter,监控你的微服务是否健康!:xie.infoq.cn/article/847...

一文带你整合arthas和springboot :blog.csdn.net/weixin_4564...

spring boot 集成arthas实现线上远程监控调优 :zhuanlan.zhihu.com/p/610030983

Arthas Tunnel:arthas.aliyun.com/doc/tunnel....

本文使用 markdown.com.cn 排版

相关推荐
+VX:Fegn08951 小时前
计算机毕业设计|基于springboot + vue在线考试管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
okseekw1 小时前
Java泛型从入门到实战:原理、用法与案例深度解析
java·后端
雨中飘荡的记忆1 小时前
Spring WebFlux详解
java·后端·spring
文攀1 小时前
Go 语言 GMP 调度模型深度解析
后端·go·编程语言
银嘟嘟左卫门1 小时前
使用openEuler进行多核性能测评,从单核到多核的极致性能探索
后端
徐行code1 小时前
C++ 核心机制深度解析:完美转发、值类别与 decltype
后端
回家路上绕了弯1 小时前
技术团队高效协作:知识分享与协作的落地实践指南
分布式·后端
JaguarJack1 小时前
如何创建和使用 Shell 脚本实现 PHP 部署自动化
后端·php
qq_348231852 小时前
Spring Boot 项目集成模块- 2
spring boot·后端