Arthas Spring Boot Starter 实战指南:应用内嵌诊断、Tunnel 远程管理与非 Spring Boot 应用接入
【免费下载链接】arthasAlibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas项目地址: https://gitcode.com/gh_mirrors/ar/arthas
本文基于仓库 site/docs/en/doc/spring-boot-starter.md 编写,并结合作者仓库源码进行纵深讲解。
导读
Arthas Spring Boot Starter 是 Arthas 为 Spring Boot 应用提供的零成本接入方案:只要在 pom 中引入一个依赖,应用启动时 Spring 就会自动拉起 Arthas 并 attach 到自身进程,开箱即用地获得在线诊断能力。本文将以 starter 的引入、配置、Endpoint 监控为核心,讲解如何在 Spring Boot 2/3 应用中内嵌 Arthas、通过 Tunnel Server 实现远程管理、加载外部命令,并给出非 Spring Boot 应用使用ArthasAgent.attach()的等价方案。
为什么需要 Arthas Spring Boot Starter
传统使用 Arthas 的方式是下载 arthas 包后用as.sh或as.bat连接目标 Java 进程,这对于本地开发、测试环境非常方便。但在生产集群、容器化部署或无法人工登录的场景下,人工 attach 成本高、难自动化。
Spring Boot Starter 则把 attach 动作完全自动化:应用启动时,Spring 容器初始化 Arthas,并 attach 自身进程。这样,应用一启动就处于可诊断状态,配合 Arthas Properties 中的 Tunnel Server 配置,还能把本地 Arthas 注册到远程管理端,实现"无人值守"的远程诊断。
::: tip Arthas 3.7.2 及以后版本同时支持 Spring Boot 2 和 Spring Boot 3。仓库源码 pom.xml 中的 profile 也印证了这一点:JDK 8~16 时仅集成测试 Spring Boot 2 示例,Spring Boot 3 示例的集成测试需要 JDK 17 及以上。 :::
快速开始:引入 Maven 依赖
在 Spring Boot 应用的pom.xml中添加如下依赖:
<dependency> <groupId>com.taobao.arthas</groupId> <artifactId>arthas-spring-boot-starter</artifactId> <version>${arthas.version}</version> </dependency>其中${arthas.version}需要替换为实际使用的版本号。引入后,应用启动时 Spring 会启动 Arthas,并 attach 自身进程,无需任何额外代码。
从源码看,starter 本身只做了薄薄一层的 Spring 集成,真正干活的组件都在它的依赖里:
- arthas-agent-attach:负责把 Arthas agent 挂载到当前 JVM;
- arthas-packaging:提供打包好的 arthas 运行资源(如
arthas-core.jar、arthas-bin.zip)。
同时,starter 以provided/optional方式依赖spring-boot-starter-actuator和spring-boot-starter-web(见 pom.xml),即不强制你的应用引入 Web/Actuator 能力,只有想通过 HTTP Endpoint 查看 Arthas 状态时才需要它们。
工作原理:从 Spring Bean 到 Arthas Agent
Starter 的核心自动化逻辑集中在 ArthasConfiguration.java,它通过 Spring Boot 的自动装配完成以下链路:
- 条件装配:
@ConditionalOnProperty(name = "spring.arthas.enabled", matchIfMissing = true),默认开启,可通过spring.arthas.enabled=false一键关闭。 - 配置收集:
@ConfigurationProperties(prefix = "arthas")将所有以arthas.*开头的配置项收集进arthasConfigMap。源码注释特别说明:之所以用一个独立的 Map 而不是只依赖ArthasProperties,是为了避免某些新版本才支持的配置项在ArthasProperties类里尚未定义。 - 配置归一化:
StringUtils.removeDashKey()把-风格的配置键(如agent-id)转成驼峰(如agentId),详见 StringUtils.java。 - 补全默认值:
ArthasProperties.updateArthasConfigMapDefaultValue()为未配置的disabledCommands注入默认值stop。 - 注入应用名:如果配置中没有
appName,自动取spring.application.name的值。 - 启动 Agent:给所有配置加上
arthas.前缀后,new ArthasAgent(mapWithPrefix, arthasProperties.getHome(), arthasProperties.isSlientInit(), null),然后调用arthasAgent.init()真正完成 attach。
init()的底层实现在 ArthasAgent.java:
- 先通过
Class.forName("java.arthas.SpyAPI")+SpyAPI.isInited()判断 Arthas 是否已在运行,避免重复 attach; - 通过
ByteBuddyAgent.install()获取当前 JVM 的Instrumentation; - 若未显式指定
arthasHome,则从 classpath 解压arthas-bin.zip到临时目录; - 加载
arthas-core.jar中的com.taobao.arthas.core.server.ArthasBootstrap,调用getInstance(inst, configMap)完成初始化; - 检查
isBind(),端口绑定失败则记录错误信息;slientInit=true时只记录错误不抛异常,否则抛出IllegalStateException。
配置属性详解
官方示例:通过 Tunnel Server 远程管理
application.properties(或application.yml)中的核心配置示例如下:
arthas.agent-id=hsehdfsfghhwertyfad arthas.tunnel-server=ws://47.75.156.201:7777/ws arthas.command-locations=/opt/arthas/ext-command.jar,/opt/arthas/ext-commands三个配置项分别解决三个问题:
| 配置项 | 作用 | 说明 |
|---|---|---|
arthas.agent-id | 设置 agent 的唯一标识 | 用于在 Tunnel Server 端唯一标识该应用实例 |
arthas.tunnel-server | 指定 Tunnel Server 地址 | Arthas 启动后通过 WebSocket 连接到该服务端,等待远程指令 |
arthas.command-locations | 指定外部命令的加载路径 | 可配置 jar 文件路径或目录路径,多个用逗号分隔 |
Spring Boot 的 relaxed binding 机制同时支持arthas.command-locations和arthas.commandLocations两种写法;在 Spring Boot 配置文件中推荐使用arthas.command-locations(-风格)。
全部受支持配置项(来自源码)
Starter 支持的所有配置项完整定义在 ArthasProperties.java,@ConfigurationProperties(prefix = "arthas")意味着所有键都以arthas.开头:
| 配置键(properties 风格) | 字段(驼峰) | 类型 | 说明 |
|---|---|---|---|
arthas.ip | ip | String | Arthas 服务监听 IP |
arthas.telnet-port/arthas.telnetPort | telnetPort | int | Telnet 端口(默认 3658) |
arthas.http-port/arthas.httpPort | httpPort | int | HTTP 端口(默认 8563) |
arthas.tunnel-server/arthas.tunnelServer | tunnelServer | String | Tunnel Server 地址 |
arthas.agent-id/arthas.agentId | agentId | String | agent 唯一标识 |
arthas.app-name/arthas.appName | appName | String | 应用名(未配置时自动取spring.application.name) |
arthas.stat-url/arthas.statUrl | statUrl | String | 上报已执行命令的统计地址 |
arthas.session-timeout/arthas.sessionTimeout | sessionTimeout | long | 会话超时时间(秒) |
arthas.username | username | String | 认证用户名 |
arthas.password | password | String | 认证密码 |
arthas.home | home | String | 指定 arthas 安装目录 |
arthas.slient-init/arthas.slientInit | slientInit | boolean | agent 初始化出错时是否静默(默认 false,抛异常) |
arthas.disabled-commands/arthas.disabledCommands | disabledCommands | String | 禁用的命令列表(默认stop) |
arthas.command-locations/arthas.commandLocations | commandLocations | String | 外部命令加载路径 |
端口与远程管理的细节
参考 Arthas Properties 中的说明:
arthas.telnetPort配置为-1时不监听 telnet 端口,arthas.httpPort同理;- 配置为
0时随机监听端口,随机端口号会记录在~/logs/arthas/arthas.log中; - 如果一台机器上部署多个应用怕端口冲突,可以都配置为随机端口或
-1,然后统一通过 Tunnel Server 使用 Arthas——这正是上面arthas.tunnel-server示例的典型场景。
默认禁用 stop 命令
::: tip 默认情况下,arthas-spring-boot-starter会禁用stop命令。 :::
这一行为在源码中有明确实现:ArthasProperties中DEFAULT_DISABLEDCOMMANDS = "stop"(ArthasProperties.java),updateArthasConfigMapDefaultValue()在用户未配置disabledCommands时写入该默认值。
原因是:starter 将 Arthas 内嵌在业务应用进程内,若允许stop命令,等于允许远程/在线把 Arthas 服务停掉,从而失去诊断能力。如需调整,可以显式配置:
arthas.disabled-commands=stop,dump关于disabledCommands与外部命令加载的完整说明,可参考 Arthas Properties 中的 "disable specify commands" 与 "Load external commands" 两节。
加载外部命令(command-locations)
arthas.command-locations用于在 Arthas 启动时加载自定义外部命令:
arthas.command-locations=/opt/arthas/ext-command.jar,/opt/arthas/ext-commands关键约束(来自 Arthas Properties):
- 每个条目可以是 jar 文件路径或目录路径,多个条目用逗号分隔;
- 目录条目只扫描当前目录下的
*.jar,不会递归; - 如果
${arthas.home}/commands目录存在,Arthas 启动时也会尝试加载其中的*.jar;显式配置的commandLocations先加载,默认目录后加载; - 外部 jar 需要通过
META-INF/services/com.taobao.arthas.core.shell.command.CommandResolver暴露CommandResolver实现; - Arthas 内置命令优先;外部命令与内置命令同名时,外部命令被跳过并写入日志。
命令行方式等价配置:--command-locations '/opt/arthas/ext-command.jar,/opt/arthas/ext-commands'。
仓库还提供了完整的外部命令开发示例:arthas-demo-external-command 模块(包含DemoExternalCommand.java与DemoExternalCommandResolver.java),以及对应的集成测试 arthas-external-command-integration-test,详细开发流程参见 Load External Commands。
通过 Actuator Endpoint 查看 Arthas 状态
Starter 内置了一个 Actuator Endpoint 用于查看 Arthas 的配置与初始化状态。
::: tip 使用该 Endpoint 需要应用引入并暴露 Actuator Endpoint。Spring Boot 中可通过management.endpoints.web.exposure.include=arthas(或*)等配置暴露,具体以 Spring Boot 官方 Production-ready Features 文档为准。 :::
假定应用端口是 8080,访问:
http://localhost:8080/actuator/arthas返回示例:
{ "arthasConfigMap": { "agent-id": "hsehdfsfghhwertyfad", "tunnel-server": "ws://47.75.156.201:7777/ws", } }Endpoint 的实现位于 ArthasEndPoint.java:
@Endpoint(id = "arthas")定义 Endpoint id;@ReadOperation的invoke()返回arthasConfigMap(即实际注入给 Arthas 的配置)以及初始化错误信息errorMessage(当 agent 初始化失败时);- 装配逻辑在 ArthasEndPointAutoConfiguration.java,同样受
spring.arthas.enabled开关控制,并且仅当 Endpoint 被 Spring Boot 暴露时才创建(@ConditionalOnAvailableEndpoint)。
这个 Endpoint 的价值在于:应用启动后即可通过 HTTP 确认 Arthas 是否成功挂载、配置是否按预期生效、以及失败时的错误原因,非常适合接入监控探活或诊断系统的自检环节。
非 Spring Boot 应用的使用方式
如果你的应用不是 Spring Boot(例如普通 Spring、Servlet、自研框架、甚至非 Spring 的 Java 应用),无法使用 starter,可以改用arthas-agent-attach+arthas-packaging两个依赖,在代码里显式调用ArthasAgent.attach()。
Maven 依赖
<dependency> <groupId>com.taobao.arthas</groupId> <artifactId>arthas-agent-attach</artifactId> <version>${arthas.version}</version> </dependency> <dependency> <groupId>com.taobao.arthas</groupId> <artifactId>arthas-packaging</artifactId> <version>${arthas.version}</version> </dependency>一行代码完成 attach
import com.taobao.arthas.agent.attach.ArthasAgent; public class ArthasAttachExample { public static void main(String[] args) { ArthasAgent.attach(); } }带配置的 attach
HashMap<String, String> configMap = new HashMap<String, String>(); configMap.put("arthas.appName", "demo"); configMap.put("arthas.tunnelServer", "ws://127.0.0.1:7777/ws"); ArthasAgent.attach(configMap);::: warning 非 Spring Boot 方式下,配置键必须是驼峰风格(如appName、tunnelServer),这与 Spring Boot 的-风格不同。只有 Spring Boot 应用才同时支持驼峰和-两种风格——因为-到驼峰的转换(StringUtils.removeDashKey)是由 starter 完成的,裸用ArthasAgent时没有这一步。 :::
ArthasAgent还提供了其他静态方法:attach(String arthasHome)可指定 Arthas 安装目录(当 classpath 中没有arthas-bin.zip资源时,例如以-javaagent之外的隔离类加载方式运行,需要显式指定 arthas 目录),详见 ArthasAgent.java。
配置风格与优先级小结
- 风格:Spring Boot 应用推荐
-风格(arthas.tunnel-server),也兼容驼峰;非 Spring Boot 的ArthasAgent.attach(configMap)只能使用驼峰。 - 优先级(来自 Arthas Properties):命令行参数 > System Env > System Properties >
arthas.properties;若希望arthas.properties拥有最高优先级,可配置arthas.config.overrideAll=true。 - 开关:通过
spring.arthas.enabled=false可整体关闭 starter 的自动 attach 与 Endpoint 装配(两个自动配置类都带有@ConditionalOnProperty(name = "spring.arthas.enabled", matchIfMissing = true))。
参考文档
- Arthas Properties:完整配置项、禁用命令、外部命令加载与配置优先级说明
- Load External Commands:外部命令开发与加载完整示例
- 核心源码:ArthasProperties.java、ArthasConfiguration.java、ArthasEndPoint.java、ArthasAgent.java
- 集成测试示例:arthas-spring-boot-starter-example(Spring Boot 2)与 arthas-spring-boot3-starter-example(Spring Boot 3)
【免费下载链接】arthasAlibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas项目地址: https://gitcode.com/gh_mirrors/ar/arthas
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考