4、应用接入Jaeger(Java):使用OpenTelemetry Java Agent自动埋点、配置导出端点与采样策略
Java 应用接入 Jaeger 最简洁的方式是使用 OpenTelemetry Java Agent。该 Agent 通过字节码增强技术自动拦截主流框架(如 Spring Boot、gRPC、Servlet、JDBC、HTTP Client 等)的调用,无需修改业务代码即可生成分布式追踪数据。本章将详细讲解 Agent 的安装、配置导出端点以及采样策略的设定。
4.1 OpenTelemetry Java Agent 自动埋点原理
Agent 在 JVM 启动时通过 javaagent 参数挂载,利用 Instrumentation API 修改目标类的字节码,在方法入口/出口插入 Span 创建与结束逻辑。整个过程对应用代码完全透明。
4.2 快速接入步骤
4.2.1 下载 Agent JAR
从 OpenTelemetry Java Instrumentation 官方 Releases 页面下载最新版本的 opentelemetry-javaagent.jar。建议固定版本号用于生产环境,避免自动升级引入不兼容变更。
4.2.2 配置 JVM 启动参数
在应用启动命令中添加以下参数,即可完成基础接入:
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.service.name=order-service \
-Dotel.traces.exporter=otlp \
-Dotel.exporter.otlp.endpoint=http://jaeger-collector:4318 \
-jar myapp.jar
| 参数 | 说明 | 示例值 |
|---|---|---|
-Dotel.service.name |
服务名称,在 Jaeger UI 中标识服务 | order-service |
-Dotel.traces.exporter |
导出器类型,otlp 为 Jaeger 推荐协议 |
otlp |
-Dotel.exporter.otlp.endpoint |
OTLP 接收端点(HTTP/gRPC) | http://jaeger-collector:4318 |
-Dotel.resource.attributes |
附加资源属性,如环境、版本 | environment=production,version=1.2.3 |
http://jaeger-collector:4317;若使用 HTTP 端口(4318),则配置为 http://jaeger-collector:4318。请根据实际部署的 Collector 协议选择。
4.3 配置导出端点
导出端点决定了 Span 数据发送的目标地址。除 JVM 参数外,也支持通过环境变量或 YAML 配置文件设定。以下为三种配置方式对比:
| 配置方式 | 优先级 | 适用场景 |
|---|---|---|
JVM 参数(-D) |
最高 | 容器化部署、启动脚本 |
| 环境变量 | 中 | Kubernetes ConfigMap/Secret |
| Agent 配置文件(YAML) | 低 | 统一配置管理、多服务共享 |
环境变量示例:
export OTEL_SERVICE_NAME=payment-service
export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger-collector:4318
Agent 配置文件示例(otel-config.yaml):
otel:
service:
name: inventory-service
traces:
exporter: otlp
exporter:
otlp:
endpoint: http://jaeger-collector:4318
headers:
- "Authorization=Bearer mytoken"
使用配置文件时,启动参数需指定:-Dotel.javaagent.configuration-file=/path/to/otel-config.yaml。
4.4 采样策略配置
采样策略控制哪些请求被记录为 Trace,直接影响存储成本和性能开销。OpenTelemetry Java Agent 支持多种采样器,通过 -Dotel.traces.sampler 参数指定。
4.4.1 常用采样器对比
| 采样器名称 | 参数值 | 行为 | 推荐场景 |
|---|---|---|---|
| 始终采样 | always_on |
记录所有 Trace | 开发/测试环境 |
| 始终不采样 | always_off |
不记录任何 Trace | 性能压测、数据清理 |
| 基于比率 | traceidratio |
按 TraceId 哈希比例采样 | 生产环境低流量服务 |
| 基于父 Span | parentbased_traceidratio |
继承父 Span 采样决策,否则按比率 | 生产环境推荐 |
4.4.2 生产环境推荐配置
生产环境建议使用 parentbased_traceidratio 采样器,并设置合理的采样比率:
# 采样 10% 的请求,并继承上游采样决策
-Dotel.traces.sampler=parentbased_traceidratio
-Dotel.traces.sampler.arg=0.1
- 高流量服务(>1000 req/s): 0.01 ~ 0.05(1% ~ 5%)
- 中流量服务(100~1000 req/s): 0.1 ~ 0.2(10% ~ 20%)
- 低流量服务(<100 req/s): 0.5 ~ 1.0(50% ~ 100%)
- 核心交易链路: 可结合 Jaeger 的 Head-Based 采样或后续的 Tail-Based 采样实现差异化策略
4.4.3 基于头部属性的自定义采样
若需要根据 HTTP 头部(如 X-Debug)或请求参数动态采样,可通过自定义 Sampler 实现。以下为 Spring Boot 中注册自定义采样器的示例:
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.trace.data.LinkData;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import io.opentelemetry.sdk.trace.samplers.SamplingResult;
import java.util.List;
public class DebugHeaderSampler implements Sampler {
private final Sampler fallback;
public DebugHeaderSampler(Sampler fallback) {
this.fallback = fallback;
}
@Override
public SamplingResult shouldSample(Context parentContext, String traceId,
String name, SpanKind spanKind,
Attributes attributes, List<LinkData> parentLinks) {
// 从 Context 中提取 HTTP 头部(需配合手动拦截器)
String debugFlag = (String) parentContext.get("X-Debug");
if ("true".equalsIgnoreCase(debugFlag)) {
return SamplingResult.recordAndSample(); // 强制采样
}
return fallback.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks);
}
@Override
public String getDescription() {
return "DebugHeaderSampler{fallback=" + fallback.getDescription() + "}";
}
}
在配置类中注册:
@Bean
public Sampler customSampler() {
Sampler fallback = Sampler.parentBased(Sampler.traceIdRatioBased(0.1));
return new DebugHeaderSampler(fallback);
}
4.5 验证接入是否成功
启动应用后,执行以下检查步骤:
- 查看应用日志: 搜索
OTel SDK initialized或OpenTelemetry Java Agent initialized确认 Agent 加载成功。 - 触发请求: 访问应用的任意 HTTP 端点,或执行一次业务操作。
- 检查 Jaeger UI: 打开 Jaeger 查询界面,在 Service 下拉框中应能看到配置的
otel.service.name。搜索最近时间段的 Trace,确认有数据展示。 - 检查 Collector 日志: 若数据未到达,查看 Jaeger Collector 日志是否有连接拒绝或协议不匹配错误。
curl 测试 OTLP HTTP 端点是否可达:curl -v http://jaeger-collector:4318/v1/traces(应返回 200 或 405,而非 Connection Refused)。
4.6 常见问题与避坑
| 问题 | 原因 | 解决方案 |
|---|---|---|
| Agent 加载后应用启动失败 | Agent 版本与 JDK 版本不兼容 | 使用与 JDK 11+ 匹配的最新 Agent 版本;JDK 8 需使用 1.32.x 及以下版本 |
| Jaeger UI 无数据 | 端点配置错误或网络不通 | 检查 otel.exporter.otlp.endpoint 协议(http/https)和端口;确认防火墙规则 |
| Span 丢失或链路不完整 | 采样比率过低或 SpanProcessor 队列溢出 | 适当提高采样比率;增加 -Dotel.spanprocessor.batch.max.queue.size=4096 |
| 自定义框架未被自动埋点 | Agent 不支持该框架版本 | 升级框架版本;或使用 OpenTelemetry API 手动埋点 |