jaeger 在 go 微服务中需显式初始化 tracer 并全程透传 context.context,否则链路断裂;须正确配置 servicename、reporter 地址与采样器,手动处理 http/grpc 的 trace header 传播,并严格管理 span 生命周期与 context 透传。

Jaeger 在 Go 微服务中不是“加个库就能用”,必须显式初始化 tracer 并透传 context.Context,否则 span 之间无法串联,所有链路都会断成单点。
初始化 Jaeger tracer 要绑定服务名并配置 reporter
服务名(serviceName)是 Jaeger UI 中识别服务的唯一标识,必须与部署时的实际服务名一致;reporter 的 localAgentHostPort 默认指向 localhost:6831,但生产环境通常需改为真实 agent 地址。忽略端口或写错 host 会导致 spans 完全不上报,且无明显错误日志。
- 使用
jaeger.NewUDPTransport时,确保 UDP 端口 6831 在目标 agent 主机上开放(非 TCP) -
jaeger.NewConstSampler(true)仅用于调试;生产环境应换为jaeger.NewProbabilisticSampler(0.01)或jaeger.NewRateLimitingSampler(2) - 若用 all-in-one 模式本地测试,启动命令必须带
--collector.host-port=:14268,否则httpReporter会失败
HTTP 请求中手动注入/提取 trace context
Go 标准库 net/http 不自动传播 trace header,必须在 handler 入口用 opentracing.HTTPHeadersExtractor 提取 parent span,再在 outbound request 中用 opentracing.HTTPHeadersCarrier 注入。漏掉任一端,跨服务调用就会生成新 traceID。
在 Golang 中使用 samber/hot 进行内存缓存,支持 LRU、LFU、TinyLFU、W‑TinyLFU、S3FIFO、ARC、TwoQueue、SIEVE、FIFO 等淘汰算法,提供 TTL、缓存加载器及分片功能。
- 提取时 key 是
uber-trace-id,不是trace-id或X-Trace-ID - 使用
req.Header.Set("uber-trace-id", ...)前,先检查req.Header.Get("uber-trace-id")是否为空,避免覆盖上游传递的 context - 若用
http.Client发起请求,务必把带 span 的context.Context传给http.NewRequestWithContext(),否则 tracer 无法关联
gRPC 场景下必须注册拦截器
gRPC 的 metadata 传播和 HTTP 不同,不注册 otgrpc.OpenTracingServerInterceptor 和 otgrpc.OpenTracingClientInterceptor,server 端永远拿不到 parent span,所有 RPC 都是 root span。
- server 初始化时:
grpc.Server(grpc.UnaryInterceptor(otgrpc.OpenTracingServerInterceptor(tracer))) - client 初始化时:
grpc.Dial(..., grpc.WithUnaryInterceptor(otgrpc.OpenTracingClientInterceptor(tracer))) - 注意
otgrpc包来自github.com/opentracing-contrib/go-grpc,不是官方 gRPC 库自带 - 如果用了 streaming,还需额外配置
StreamServerInterceptor和StreamClientInterceptor
Span 生命周期管理容易误用 defer
常见错误是在 handler 开头创建 span 后直接 defer span.Finish(),但 span 关闭过早会导致子 span(如 DB 查询、下游 HTTP 调用)无法被父 span 包含——因为父 span 已结束,新 span 只能变成孤儿。
- 正确做法:每个逻辑块(如 DB 查询)创建自己的 child span,并在其作用域内
defer childSpan.Finish() - 主 span 应在 handler 最后显式
span.Finish(),而非 defer - 若 handler 中有 goroutine 异步操作,必须用
opentracing.ContextWithSpan(ctx, span)传递,否则 goroutine 内无法获取当前 span
最常被跳过的环节是 context 透传:从 HTTP handler 到业务逻辑层、再到 DB 调用或下游 client,每层都得显式接收并传递带 span 的 context.Context,少一层,链路就断一次。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










