直接用 composer require openzipkin/zipkin-php:^2.0 安装,必须显式配置 endpoint、注入 b3 headers 并调用 $span->finish(),否则 zipkin 界面为空;endpoint ip 须为宿主机/集群真实地址而非 127.0.0.1,reporter url 必含 /api/v2/spans 后缀,guzzle 透传需手动 injector 注入 traceparent,且 span 不 finish 则永不上报。

直接用 composer require zipkin/zipkin 就能装,但装完不配置 endpoint、不注入 B3 headers、不 finish span,Zipkin 界面永远是空的——这不是库没生效,而是上报链路断在了第一步。
安装命令必须带版本约束,否则可能不兼容 PHP 8.2+
官方 zipkin/zipkin 包已停止维护,当前稳定可用的是社区维护分支 openzipkin/zipkin-php(注意 vendor 名不同)。直接运行:
composer require openzipkin/zipkin-php:^2.0
不加 ^2.0 容易拉到 v1.x 版本,它依赖老版 guzzlehttp/guzzle,在 PHP 8.2+ 下会因弃用警告触发 fatal error。如果已有冲突,先执行 composer remove zipkin/zipkin 再重装。
Endpoint 和 Reporter 必须显式指定,不能靠 createFromGlobals() 自动推导
Endpoint::createFromGlobals() 在 CLI 或 Docker 容器里大概率生成错误 service name 和 IP,比如把 PHP_SAPI 推成 cli,或把容器内网 IP 当成本地地址。正确写法是手动构造:
-
$endpoint = new Zipkin\Endpoint('user-service', '10.0.1.5', 8080);—— IP 必须是服务实际监听的宿主机/集群 IP,不是127.0.0.1 -
$reporter = new Zipkin\Reporters\Http('http://zipkin:9411/api/v2/spans');—— URL 必须含/api/v2/spans后缀,少一个字符就 404 - 别用
Http默认超时(3 秒),高并发下容易丢 span,建议显式传 options:new Zipkin\Reporters\Http($url, ['timeout' => 5])
Guzzle 请求透传 traceparent 头必须手动做,中间件不是自动生效的
Hyperf 或 Laravel 的 HTTP client 中间件不会自动注入 tracing header,你得自己调用 injector:
- 先从当前 span 提取上下文:
$context = $tracer->getCurrentSpan()->getContext(); - 再用
Zipkin\Propagation\B3StringInjector注入:$injector($context, $headers); - 最后确保请求发出后调用
$span->finish()—— 不 finish,span 永远卡在内存里不上报 - 别依赖
$tracer->flush():Guzzle 连接复用时 flush 可能清掉未发送的 buffer,应在每个 span 结束后立刻 finish
Zipkin UI 查不到数据?先确认这三件事
常见静默失败根本不是代码问题,而是环境配置错位:
- 检查 Zipkin 容器是否真在监听
9411:运行curl -v http://localhost:9411/health,返回200 OK才算通 - 确认 PHP 服务和 Zipkin 是否在同一网络:Docker Compose 里要共用 network,不能一个用
bridge一个用host - 查 PHP 错误日志里有没有
Failed to send spans to Zipkin—— 如果有,说明 reporter 配置错或网络不通,Httpreporter 默认不抛异常,只打 warning
最常被忽略的是:span 的 parentId 为空时,Zipkin 会把它当 root span 展开,但如果你没调用过 extract() 解析上游 X-B3-TraceId,所有 span 都是孤立的,根本连不成链。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











