14. 分布式链路追踪

OpenTelemetry 标准化链路追踪、Jaeger/Zipkin 实战、采样策略、Span 上下文传递与可观测性落地

分布式链路追踪记录请求在微服务间的完整调用路径,帮助定位性能瓶颈和故障根因。OpenTelemetry 正在统一 Metrics、Logs、Traces 三大信号标准。

1. 核心概念

概念说明
Trace一次请求的完整调用链
Span调用链中的单个操作单元
SpanContextTraceID + 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

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「distributed-systems」更多文章

  1. 分布式高可用架构模式:多活、容灾、降级与 K8s 编排高可用
  2. 分布式链路追踪实战:OpenTelemetry、Jaeger 与 W3C Trace Context
  3. 分布式缓存深度策略:Redis Cluster、一致性哈希与多级缓存架构