分布式链路追踪:从日志拼查到 Trace 一键

单体时代排查:一个请求,一个日志文件,顺序看下来就行。微服务时代:一个请求经过 8 个服务,日志散在 8 个地方,“拼日志"是每个排查人的噩梦。链路追踪(Distributed Tracing)就是解决这个问题的。

一、痛点

1 2 3 " . . . A P I 6 o r " d e r _ × i d . 8 . 0 . 0 线 m s =

二、核心概念

Trace 与 Span

T S r p a a c n a e p i T - o r g r a a d c t e e e r p c w - a o a s y u y e m p r e o ( v n n s i t - p c - s a e s e n e r : ( r v s v i p i c a c e n e : ( ) ( s s p p a a n n : ) : ) )

三个 ID

t s p r p a a a r c n e e _ n _ i t i d _ d s p a n _ i d

三、实现:上下文传递

关键:trace_id 必须在服务间传递(HTTP header / gRPC metadata / MQ 消息头)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// 入口:生成 trace_id
func Middleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        traceID := c.GetHeader("X-Trace-Id")
        if traceID == "" {
            traceID = uuid.New()          // 入口生成
        }
        c.Set("trace_id", traceID)
        // 下发给下游
        c.Header("X-Trace-Id", traceID)
        c.Next()
    }
}

// 下游:从 header 取(没有就新生成——链路断了要告警)
traceID := c.GetHeader("X-Trace-Id")

gRPC 传递

1
2
3
4
5
6
7
// 用 metadata 传递
md := metadata.Pairs("x-trace-id", traceID)
ctx = metadata.NewOutgoingContext(ctx, md)
// 服务端
if md, ok := metadata.FromIncomingContext(ctx); ok {
    traceID = md.Get("x-trace-id")[0]
}

MQ 传递:消息头带 trace_id(RabbitMQ headers / Kafka headers)。

四、采集与存储

采样策略(成本控制)

1 0 % = + S p E 1 a + R 0 n R % O R / / 2 0 + 9 9 %

存储选型

J Z S a i k e p y g k W e i a r n l C k l i i n c g k E H S J o / a u C v s a a e s s a n S d p r a a n

五、落地效果

1 2 3 4 " . . . . " T r a " c 3 e 0 Q P S / " 6 0 0 m s

六、踩坑记录

  1. 链路断裂:下游没接 header → trace_id 丢失 → 入口生成了,下游自己建新 ID → 所有服务必须统一 SDK 传递
  2. 异步链路丢失:goroutine 里没传 context → 异步任务不在链路上 → 协程创建时带上 trace context
  3. 采样把错误丢了:只采样 10%,错误请求恰好没采到 → 错误必须全量采集
  4. Span 字段太多:采集 30 个字段 → 存储翻倍 → 只留关键字段(service/操作/耗时/状态/错误)

七、与日志/指标的配合

M L T e o r t g a r s c i e c s s T L r o a g c s e > 5 % Q P / S / / /

总结

链路追踪的核心认知:

  1. Trace = 一次请求的完整树:trace_id 贯穿 + span 记录每个环节
  2. 上下文传递是地基:HTTP/gRPC/MQ 全链路传 trace_id,断了就是白做
  3. 采样要有策略:正常 10% + 错误全采 + 核心接口全量
  4. 三层配合:指标触发告警、链路定位、日志看细节

微服务排查的分水岭:会不会用 Trace。 有了全链路视图,“这个请求到底经历了什么"就不再是拼出来的,是看出来的。