Skip to content

Java Agent

SkyWalking Java Agent 通过字节码插桩(Bytecode Instrumentation)在 JVM 启动时随应用加载,自动拦截受支持的框架调用,采集 Trace、Metric 和 Profile,无需修改业务代码。它是 SkyWalking 在 Java 生态中最成熟、最常用的接入方式。

加载方式

Java 通过 -javaagent JVM 参数在应用启动前加载 Agent:

shell
-javaagent:/app/skywalking-agent/skywalking-agent.jar \
-Dskywalking.agent.service_name=abc \
-Dskywalking.collector.backend_service=localhost:11800 \
  • -javaagent 指向 skywalking-agent.jar
  • -Dskywalking.agent.service_name 设置服务名(Service Name),对应 OAP 中的一个 Service。
  • -Dskywalking.collector.backend_service 设置 OAP 的 gRPC 地址(默认 127.0.0.1:11800)。

安装包从官方下载页获取。Agent 版本应与 OAP 大版本兼容。

字节码插桩(Bytecode Instrumentation)

Agent 利用 Java Instrumentation API(premain / agentmain)在类加载时改写字节码,在目标方法的入口/出口处插入埋点代码,实现"自动打点":

概念说明
premainJVM 启动时、应用类加载前执行,适合常规接入(-javaagent
agentmain运行期动态挂载(attach),适合热接入
Transform通过 ClassFileTransformer 改写类字节码
类隔离Agent 核心类与业务类隔离,避免冲突

插桩发生时机与用户请求无关,业务代码不需要 import 任何 SkyWalking 类,这是其低侵入的关键。

插件体系

SkyWalking Agent 的核心能力由**插件(Plugin)**提供。每个插件针对一类框架或技术栈做插桩:

  • Web 框架:Spring MVC、Spring Boot、Tomcat、Jetty 等
  • RPC:Dubbo、gRPC、Spring Cloud 等
  • HTTP Client:RestTemplate、HttpClient、OkHttp、Feign 等
  • 数据库:JDBC、MyBatis、Redis、MongoDB 等
  • 消息队列:Kafka、RocketMQ、RabbitMQ 等

插件默认启用,部分需要显式配置或按 @Trace 注解/手动 API 接入。生产环境建议只启用实际使用的插件,减少无谓的插桩开销和潜在兼容问题。

关键配置

常用 -D 配置项(也可通过 agent/config/agent.config 文件或环境变量):

配置项作用
skywalking.agent.service_name服务名,对应一个 Service
skywalking.agent.instance_name实例名,缺省为自动生成的 UUID
skywalking.agent.namespace命名空间,用于区分多套环境
skywalking.collector.backend_serviceOAP gRPC 地址
skywalking.agent.sample_n_per_3_secs采样率:每 3 秒抽样条数,-1 表示全采
skywalking.agent.ignore_suffix忽略的请求后缀(如静态资源)
skywalking.agent.trace_segment_ref_limit_per_span每个 Span 的 Segment 引用上限
skywalking.agent.active_v2_header是否发送 sw8 传播 Header

配置规则:命令行 -D 优先级最高,其次环境变量,最后 config 文件

采样

Java Agent 使用头部采样:在 Trace 根部决定是否采样,之后整条链路保持一致,避免收集"半条链路"。

skywalking.agent.sample_n_per_3_secs 控制每 3 秒抽取的请求条数,-1 表示全量采样。生产环境通常不全采:

  • 全采开销高、存储成本大。
  • 但慢请求/错误请求应尽量采到,否则定位问题会漏样本。

采样率说明与取舍,参见 APM / 采样

Trace ID 注入与上下文传播

Agent 在处理请求入口生成 traceId,并把追踪上下文写入下游调用的协议头,实现跨进程传播:

  • HTTP:往请求头写入 sw8(SkyWalking 自有钱包格式),也支持 W3C traceparent
  • gRPC:写入 gRPC Metadata。
  • MQ:写入消息 Header。

下游进程的 Agent 读到这些 Header 后,续接同一 traceId,从而把链路连成一条。若 Header 未对齐或线程上下文丢失,会出现断链。

跨进程传播的协议与原理详见链路追踪原理

异步与并发场景

Java 默认用 ThreadLocal 保存当前 Trace 上下文。跨线程/异步场景不会自动传递上下文,需要配合插件或手动处理:

  • Thread Pool / Executor:需要传递上下文,否则子线程产生"孤儿 Span"。
  • 异步 Servlet / WebFlux / Reactive:上下文切换频繁,依赖插件支持或 Async 相关 API。

社区常用做法是使用 SkyWalking 提供的跨线程工具或依赖各框架的异步插件。若发现"链路在异步处断开",优先检查这里。

手动埋点(可选)

无法自动插桩的代码可用 API 手动埋点(例如自定义业务 Span):

java
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;

public class BizService {
    @Trace(opName = "handleBiz", operationName = "doSomething")
    public void doSomething() {
        System.out.println(TraceContext.traceId());
    }
}

手动埋点适合自动插件覆盖不到的关键业务逻辑,但应克制使用,避免埋点过密影响性能与可读性。

与语言 Agent 的差异

Java Agent 依赖 JVM 的字节码插桩能力,最为成熟。其它语言实现方式不同、能力也有差异:

语言实现方式成熟度
Java字节码插桩(Instrumentation API)最完整,插件最多
GoSDK / 手动埋点为主(编译期)需配合框架注入
Python运行时包装/hook中等
Node.js运行时拦截(继承原生模块)中等

非 Java 环境往往需要更多手动接入,或通过 OpenTelemetry 等链路接入 OAP。

常见问题排查

症状排查方向
页面无数据Agent 是否加载成功、backend_service 是否可达、版本是否兼容
部分请求没链路采样率是否过低、异步线程是否丢上下文
服务名错误service_name 配置是否唯一、是否带上了 namespace
Trace 断链检查 HTTP/ gRPC / MQ 的 Header 传播,及异步场景
高开销只启用用到的插件、降低采样率、忽略静态资源后缀

结合 UI 查看 Agent 上报状态与数据链路,排障思路可参考告警与指标