分布式链路追踪记录请求在微服务间的完整调用路径,帮助定位性能瓶颈和故障根因。OpenTelemetry 正在统一 Metrics、Logs、Traces 三大信号标准。
1. 核心概念
| 概念 | 说明 |
|---|---|
| Trace | 一次请求的完整调用链 |
| Span | 调用链中的单个操作单元 |
| SpanContext | TraceID + SpanID + Flags,跨服务传递 |
| Baggage | 跨 Span 传递的键值对元数据 |
Trace (user-request):
[Span: GET /api/order] 10ms
├── [Span: queryUser] 3ms
├── [Span: queryInventory] 2ms
└── [Span: createPayment] 4ms
└── [Span: callBankAPI] 3ms
2. OpenTelemetry 自动埋点
2.1 Java Agent
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=order-service \
-Dotel.exporter.otlp.endpoint=http://otel-collector:4317 \
-jar order-service.jar
2.2 手动埋点
Tracer tracer = GlobalOpenTelemetry.getTracer("order-service");
Span span = tracer.spanBuilder("createOrder")
.setSpanKind(SpanKind.SERVER)
.startSpan();
try (Scope scope = span.makeCurrent()) {
span.setAttribute("order.id", orderId);
span.setAttribute("user.id", userId);
// 内部 Span
Span dbSpan = tracer.spanBuilder("saveOrder")
.setParent(Context.current().with(span))
.startSpan();
try {
orderRepository.save(order);
} finally {
dbSpan.end();
}
} catch (Exception e) {
span.recordException(e);
span.setStatus(StatusCode.ERROR);
throw e;
} finally {
span.end();
}
3. 上下文传递
// HTTP 客户端:注入上下文
TextMapSetter<HttpURLConnection> setter = (carrier, key, value) ->
carrier.setRequestProperty(key, value);
openTelemetry.getPropagators().getTextMapPropagator()
.inject(Context.current(), connection, setter);
// 服务端:提取上下文
TextMapGetter<HttpServletRequest> getter = new TextMapGetter<>() {
public String get(HttpServletRequest req, String key) {
return req.getHeader(key);
}
public Iterable<String> keys(HttpServletRequest req) {
return () -> req.getHeaderNames().asIterator();
}
};
Context ctx = openTelemetry.getPropagators().getTextMapPropagator()
.extract(Context.current(), request, getter);
W3C Trace Context 标准头部:
traceparent:00-{trace-id}-{span-id}-{flags}tracestate: 厂商扩展信息
4. 采样策略
| 策略 | 说明 | 适用 |
|---|---|---|
| AlwaysOn | 全量采样 | 测试环境 |
| AlwaysOff | 不采样 | 生产关闭 |
| TraceIdRatio | 按 TraceID 比例采样 | 生产常用 |
| ParentBased | 跟随父 Span 决策 | 保证完整链路 |
| RateLimiting | 速率限制(如 100 spans/s) | 流量高场景 |
# OpenTelemetry Collector 配置
processors:
tail_sampling:
decision_wait: 10s
policies:
- name: errors
type: status_code
status_code: { status_codes: [ERROR] }
- name: slow_requests
type: latency
latency: { threshold_ms: 1000 }
5. Jaeger 部署
# docker-compose
version: '3'
services:
jaeger:
image: jaegertracing/all-in-one:1.45
ports:
- "16686:16686" # UI
- "14268:14268" # Collector HTTP
- "4317:4317" # OTLP gRPC
environment:
- COLLECTOR_OTLP_ENABLED=true
访问 http://localhost:16686 查看调用链。
6. Metrics + Logs + Traces 关联
# 统一标签实现三信号关联
import logging
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
current_span = trace.get_current_span()
trace_id = current_span.get_span_context().trace_id
# Log 中嵌入 trace_id
logger.info("Processing order", extra={"trace_id": f"{trace_id:032x}"})
# Metrics 中嵌入 trace_id(Exemplar)
request_duration.observe(duration, {"trace_id": f"{trace_id:032x}"})
总结
- OpenTelemetry 是标准:新项目直接使用 OTel SDK
- 自动埋点覆盖 80%:Java/Python/Node.js Agent 自动收集
- 采样是生产关键:Tail-based 采样捕获异常链路
- 三信号关联:TraceID 串联 Metrics/Logs/Traces
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。