zipkin仅负责链路追踪,不提供cpu、qps等指标监控,需搭配prometheus+grafana;服务端必须先启动,客户端才能正常上报;务必使用v0.5+版zipkin-go,正确配置reporter、服务名及span生命周期管理。

Zipkin 本身不提供监控指标(如 CPU、QPS、错误率),它只做链路追踪;想用它当“传统链路运行监控后端”,本质是误用——你真正需要的是把 Zipkin 当作 trace 数据的收集与展示层,再搭配 Prometheus + Grafana 做指标监控。
Zipkin 服务端必须先跑起来,否则客户端静默丢数据
zipkin-go 不托管服务端,所有 span 都发往外部 Zipkin 实例。没这步,tracer.StartSpan 看似正常,实际全丢。
- 用 Docker 启动最稳:
docker run -d -p 9411:9411 openzipkin/zipkin - 验证是否可用:
curl -s http://localhost:9411/health应返回{"status":"UP"} - 容器内部署时,别写
localhost:9411—— 改成真实服务名,比如zipkin.default.svc.cluster.local:9411 - 如果 Zipkin 前面挂了 Nginx 或开了 Basic Auth,URL 要带认证头或路径前缀,且需自定义
http.Client传给 reporter
客户端必须用 openzipkin/zipkin-go v0.5+,别碰已归档的 opentracing 封装库
openzipkin/zipkin-go-opentracing 已归档,依赖过时的 OpenTracing 接口,上报格式不兼容 Zipkin v2 API,会导致 400 Bad Request 或 unsupported protocol scheme "" 错误。
- 正确引入:
github.com/openzipkin/zipkin-go(v0.5 推荐) - 初始化 reporter 必须非 nil:
reporter := zipkinhttp.NewReporter("http://zipkin:9411/api/v2/spans") - tracer 创建时必须传 reporter 和有效服务名:
zipkin.NewTracer(reporter, zipkin.WithName("auth-service")),空服务名 → UI 显示unknown - 别自己拼
http.Post调/api/v2/spans,用 reporter 封装好的逻辑
HTTP 服务自动埋点要插对位置,Gin/Echo 等框架不能直接套 net/http 中间件
zipkinhttp.NewServerMiddleware 只适配标准库 net/http,插在 http.ServeMux 或 http.ListenAndServe 前才生效。Gin 用户得用 gin-contrib/zipkin,硬套会漏路径、无上下文。
- 标准库示例:中间件必须在
http.Handle之前注册,且 handler 要接收http.ResponseWriter和*http.Request - 必须透传 B3 头:
X-B3-TraceId、X-B3-SpanId等,否则跨服务链路断裂 - 中间件只处理入站请求;出站调用(如
http.Get)需手动创建 child span 并defer span.Finish() - handler panic 时 span 不会自动标 error,得 recover 后显式
span.Tag("error", "true")
Span 生命周期必须手动管理,defer span.Finish() 不是可选项
忘记 span.Finish() 是最常见问题:UI 显示 “incomplete”,耗时为 0,甚至内存缓慢泄漏。
- 每个
tracer.StartSpan必须配对defer span.Finish(),且放在函数开头附近,避免被 if 分支跳过 - 即使出错提前 return,也要 finish;否则 context 泄漏,后续 goroutine 无法继承 trace
- 跨 goroutine 传递必须显式用
span.Context()拿 context,再传参进去——Go 不自动绑定到 goroutine - 数据库、gRPC 等出站调用,要用对应 client wrapper(如
zipkinhttp.NewClient)或手动 inject/extract
真正难的不是集成 Zipkin,而是让 trace 上下文在 HTTP、gRPC、DB、消息队列之间无缝流动;漏掉任意一环,链路就断成碎片。服务名、reporter URL、span.Finish() 这三件事,少一个都查不到完整链路。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











