必须先启动zipkin server(如docker run -d -p 9411:9411 openzipkin/zipkin),再用openzipkin/zipkin-go初始化tracer并配httpservermiddleware自动埋点,注意服务端健康、b3头透传及context显式跨goroutine传递。

直接上结论:用 openzipkin/zipkin-go,别碰 zipkin-go-opentracing(已归档)或 jaeger-client-go(那是 Jaeger 的),且必须先跑通 Zipkin Server,否则所有 span 都静默丢弃。
Zipkin Server 没起来,客户端再配也没用
这是最常卡住的点——zipkin-go 只负责采集和上报,不托管服务端。你得自己启动一个:
- 推荐方式:
docker run -d -p 9411:9411 openzipkin/zipkin - 验证是否可用:
curl -s http://localhost:9411/health应返回{"status":"UP"} - 上报地址必须写全:
http://localhost:9411/api/v2/spans,漏掉/api/v2/spans会 404 且无日志提示 - 如果用了 Nginx 做反向代理,确认它没 strip 掉
X-B3-*header(需加underscores_in_headers on;)
HTTP 服务自动埋点别手写 StartSpan/Finish
用 zipkin.HTTPServerMiddleware 是标准库场景;但 Gin/Echo 等框架要换对应封装:
在 Golang 中使用 samber/hot 进行内存缓存,支持 LRU、LFU、TinyLFU、W‑TinyLFU、S3FIFO、ARC、TwoQueue、SIEVE、FIFO 等淘汰算法,提供 TTL、缓存加载器及分片功能。
- Gin 用户必须用
gin-contrib/zipkin,不是zipkin-go自带的中间件(它只适配net/http) - 中间件注册顺序很重要:必须在路由注册之前,否则 path 捕获不全
- 上游调用方必须透传
X-B3-TraceId、X-B3-SpanId、X-B3-ParentSpanId,否则每个请求都是新 trace - handler panic 时 span 不会自动标 error,需手动
span.Tag("error", "true")并span.Finish()
跨 goroutine 必须显式传 context
zipkin-go 的 Span 不绑定 goroutine,也不全局可见:
- 主线程 start span 后,用
span.Context()提取带 trace 信息的context.Context - 把这个
ctx显式传给子 goroutine 的函数参数,比如go doWork(ctx) - 漏这步,所有
go func里的 span 都是孤立的,链路断开 - 别依赖框架自动传播——Gin 的
c.Request.Context()是干净的,不带 span,得你自己塞进去
v0.4+ 默认用 v2 API,collector 地址和 batch 行为要调
新版 client 默认走 /api/v2/spans,老服务端会 404:
- 初始化 reporter 时,用
zipkin.NewReporter(zipkin.NewHTTPCollector("http://localhost:9411/api/v2/spans", zipkin.HTTPBatchSize(1))) -
zipkin.HTTPBatchSize(1)是调试期关键项:避免攒批导致延迟,上线可调大(如 10) - 别用
zipkin.NewUDPTransport:Go 的net.Conn.WriteTo在高并发下易丢包,且 Zipkin Server 默认不监听 UDP - 如果服务端启用了 Basic Auth,得自己构造 HTTP client 加
Authorizationheader,zipkin-go不处理
真正容易被忽略的是:Zipkin Server 的健康状态、header 透传完整性、以及 context 在 goroutine 间的显式传递——这三处出问题,trace 看起来“没数据”或“断链”,但日志里几乎不报错。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










