【SkyWalking从入门到精通】第07篇:远程调试那些事——线上SkyWalking Agent的正确调试姿势

📅 2026/7/7 2:54:00
【SkyWalking从入门到精通】第07篇:远程调试那些事——线上SkyWalking Agent的正确调试姿势
上一篇【第06篇】JavaAgent原理——SkyWalking无侵入探针的魔法秘密下一篇【第08篇】Service Mesh入门——下一代微服务通信架构你了解多少摘要SkyWalking的探针插件出了问题测试环境复现不了生产环境又不能加日志重新发布——这是很多SkyWalking开发者和运维人员头疼的问题。这时候远程调试Remote Debug就是你的救命稻草。本篇讲清楚JDWP协议原理、JVM远程调试参数配置、IDEA连接远程调试的完整步骤以及如何安全地在测试环境中调试SkyWalking Agent代码。一、远程调试是什么本地调试大家都熟悉在IDE里打断点启动Debug模式代码执行到断点处就暂停你可以查看变量值、单步执行。远程调试的目标一样只是被调试的程序运行在另一台机器或者另一个JVM进程上你的IDE从本地发出调试指令控制远端JVM的执行。┌─────────────────────────────────────────────────────────────┐ │ 远程调试架构 │ │ │ │ 你的电脑IDEA 服务器 │ │ ┌──────────────────┐ TCP连接 ┌──────────────────┐ │ │ │ │ ←────────→ │ │ │ │ │ IDEA Debugger │ │ 目标JVM进程 │ │ │ │ │ │ SkyWalking │ │ │ │ 打断点、查变量、 │ │ Agent │ │ │ │ 单步执行 │ │ │ │ │ └──────────────────┘ └──────────────────┘ │ │ │ │ 调试指令通过JDWP协议传输 │ └─────────────────────────────────────────────────────────────┘二、JDWP协议Java调试的基础设施远程调试能工作依赖于JVM内置支持的**JDWPJava Debug Wire Protocol**协议。JDWP是Java平台调试体系JPDA的一部分它定义了调试器如IDEA与被调试JVM之间的通信协议包括设置/清除断点暂停/继续线程执行查询变量值获取调用栈当你在JVM启动参数里加上特定参数就开启了JDWP监听调试器就可以通过网络连接过来控制JVM了。三、开启远程调试的JVM参数基本格式# Java 5-8版本的写法旧式java-Xdebug-Xrunjdwp:transportdt_socket,servery,suspendn,address5005\-jaryour-app.jar# Java 9版本的推荐写法新式更简洁java-agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005\-jaryour-app.jar参数详解参数含义常用值transport传输方式dt_socketTCP/IP最常用server是否以服务模式等待连接y被调试端等待调试器连接suspend是否在启动时挂起等待调试器n正常启动不等待/y等调试器连接后才继续address监听地址和端口5005端口号/*:5005Java9接受所有IPsuspendyvssuspendn的使用场景suspendn应用正常启动调试器随时可以连入适合已运行的服务suspendy应用启动后立即挂起等待调试器连接后才继续执行适合调试启动过程比如Agent的premain方法四、调试SkyWalking Agent代码SkyWalking Agent在应用启动时就开始工作premain方法调试Agent代码有其特殊之处。场景1调试Agent插件运行时逻辑如果你想调试某个插件的拦截器比如Spring MVC插件可以这样设置# 启动你的Spring Boot应用同时加载SkyWalking Agentjava\-javaagent:/path/to/skywalking-agent/skywalking-agent.jar\-agentlib:jdwptransportdt_socket,servery,suspendn,address5005\-jaryour-spring-boot-app.jar注意-javaagent和-agentlib:jdwp两个参数可以同时存在互不干扰。场景2调试Agent启动过程premain方法如果你想调试Agent初始化过程需要suspendyjava\-javaagent:/path/to/skywalking-agent/skywalking-agent.jar\-agentlib:jdwptransportdt_socket,servery,suspendy,address5005\-jaryour-spring-boot-app.jar# 应用会挂起等待你的IDEA连接上来后才继续执行五、IDEA配置Remote Debug步骤1创建Remote调试配置打开Run → Edit Configurations点击号选择Remote JVM Debug配置如下Name: SkyWalking Agent Debug Host: localhost或者服务器IP Port: 5005IDEA会自动生成对应的JVM启动参数复制到你的应用启动命令里。步骤2导入SkyWalking源码要在Agent代码里打断点你需要让IDEA知道源码位置# 方式1直接克隆SkyWalking源码仓库推荐gitclone https://github.com/apache/skywalking.gitcdskywalkinggitcheckout v8.x.x# 切换到与你部署版本对应的Tagmvn compile-DskipTests# 编译不跑测试节省时间# 方式2在Maven依赖里添加sources# SkyWalking的源码包可以在Maven中央仓库下载将源码项目在IDEA中打开或者在Remote调试时IDEA会自动匹配classpath中的class与源码。步骤3打断点并连接在SkyWalking源码中的关键位置打断点例如// 在插件拦截器里打断点看每次HTTP请求的追踪过程// 位置apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/...publicclassAbstractSpringMVCHandlerMethodInterceptor{publicvoidbeforeMethod(...){// 在这里打断点 ← 断点}}然后在IDEA中点击Debug 按钮绿色虫子图标连接到远程JVM。当应用处理一次HTTP请求时执行到你的断点处IDE就会暂停你可以查看contextCarrier里的TraceId是什么request请求的Header里是否有上游的追踪上下文span对象的完整属性六、在Docker/Kubernetes环境中的远程调试现在很多应用运行在容器里远程调试需要额外处理端口映射。Docker方式# Dockerfile中的JVM启动命令 ENV JAVA_OPTS-agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005 # 运行容器时映射调试端口 docker run -p 5005:5005 -p 8080:8080 your-app-image# 本地IDEA连接到 localhost:5005 即可Kubernetes方式kubectl port-forward# 找到运行中的Podkubectl get pods-nyour-namespace# 临时将Pod的5005端口转发到本地kubectl port-forward pod/your-app-pod-name5005:5005-nyour-namespace# 这个命令运行期间IDEA连接localhost:5005就能调试Pod内的应用七、生产环境的注意事项⚠️远程调试在生产环境是非常危险的操作必须遵守以下原则1. 永远不要在生产环境开启调试端口调试端口一旦暴露任何能访问该端口的人都可以暂停JVM执行制造服务停止可以读取JVM内存中的所有变量包括密码、密钥等同于给攻击者提供了完整的服务器控制权2. 只在测试/预发环境使用正确流程1. 在测试环境复现问题 2. 启动远程调试 3. 调试分析根因 4. 修复后关闭调试端口 5. 部署到生产3. 调试完毕立即关闭即使在测试环境调试完毕也应立即重启应用移除调试参数防止误操作。4. 使用防火墙限制访问如果确实需要在内网服务器上开启调试一定要通过防火墙限制只有特定IP可以访问调试端口# 只允许特定IP开发机器访问5005端口iptables-AINPUT-ptcp--dport5005-s192.168.1.100-jACCEPT iptables-AINPUT-ptcp--dport5005-jDROP八、快速排查Agent问题的其他手段当远程调试不方便时还有几种快速定位Agent问题的方法方法1开启Agent日志# agent.config中设置日志级别 logging.levelDEBUG logging.file_nameskywalking-api.log调试模式下Agent会输出详细的插件加载、Span创建等日志。方法2使用官方的探针测试框架SkyWalking官方提供了Plugin Test框架可以在本地JUnit测试中运行探针不需要启动真实应用// 插件单元测试示例RunWith(PowerMockRunner.class)publicclassSpringMVCInterceptorTest{TestpublicvoidtestBeforeMethod()throwsThrowable{// 模拟HTTP请求环境// 验证Span是否被正确创建// 验证TraceId是否正确传播}}方法3使用skywalking-eyes工具SkyWalking项目还提供了skywalking-eyes工具可以扫描探针行为验证插件是否正常工作。本篇小结Java远程调试基于JDWP协议通过在JVM启动参数中加入调试代理使得IDE可以通过网络控制远端JVM执行关键参数-agentlib:jdwptransportdt_socket,servery,suspendn,address5005suspendy适合调试启动过程Agent的premain阶段IDEA配置创建Remote JVM Debug配置连接对应IP:PortKubernetes环境使用kubectl port-forward转发调试端口生产环境永远不要开启只在测试/预发环境使用下一篇我们转换视角介绍Service Mesh——SkyWalking监控体系的另一个重要战场。上一篇【第06篇】JavaAgent原理——SkyWalking无侵入探针的魔法秘密下一篇【第08篇】Service Mesh入门——下一代微服务通信架构你了解多少