Hyperf 分布式链路追踪(Tracer)实战:基于 OpenTracing 集成 Zipkin 与 Jaeger 后端Web框架微服务RPC框架异步编程【免费下载链接】hyperf A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.项目地址https://gitcode.com/hyperf/hyperf点击查看免费下载在微服务架构中单个业务请求往往要横跨三四个乃至数十个服务排查问题异常困难。本指南基于 Hyperf 官方提供的hyperf/tracer组件讲解如何通过 OpenTracing 协议集成 Zipkin、Jaeger 等链路追踪系统覆盖组件安装、驱动配置、采样器替换、Span Tag 定制以及自定义驱动扩展帮助你快速定位调用链瓶颈与故障点并依据链路信息优化服务。为什么微服务需要链路追踪在微服务场景下一次业务请求最少会穿越 34 个服务多则几十个甚至更多。当请求出现延迟或报错时仅靠单机日志无法还原完整的调用路径难以定位问题究竟发生在哪一个服务、哪一个调用环节。链路追踪Call Chain Tracing / Distributed Tracing通过为每个请求生成唯一的 Trace ID并将各服务间的调用关系动态串成调用链从而快速定位问题节点依据调用链时间线与状态码迅速缩小故障范围量化调用性能查看每个 Span 的耗时找出慢调用与瓶颈服务支撑容量规划结合链路信息对下游服务进行针对性的扩容与调优。组件概览hyperf/tracer 与 OpenTracing在 Hyperf 中链路追踪能力由hyperf/tracer组件提供。该组件基于 OpenTracing 协议实现目前内置了对 Zipkin 与 Jaeger 两套系统的集成ZipkinTwitter 开源的全链路追踪系统通过 HTTP 或 Kafka 上报 Span 数据JaegerCNCF 旗下的分布式追踪平台默认通过 UDP本地 Agent上报数据。同时由于实现遵循 OpenTracing 规范你完全可以在组件之上编写自定义实现接入其他兼容 OpenTracing 协议的追踪后端。从源码结构看组件内部按职责划分清晰src/tracer 下包含驱动适配器Adapter/、AOP 切面Aspect/、中间件Middleware/、事件监听器Listener/、Span 构建与上下文管理等核心模块。安装与初始化通过 Composer 安装组件在项目根目录执行composer require hyperf/tracerhyperf/tracer默认安装 Zipkin 相关依赖。如果希望使用 Jaeger需要额外安装对应的 PHP 客户端依赖composer require jonahgeorge/jaeger-client-php发布组件配置若config/autoload/opentracing.php尚不存在可通过 Hyperf 的发布命令一键生成php bin/hyperf.php vendor:publish hyperf/tracer发布后得到的配置文件即 src/tracer/publish/opentracing.php 的副本它是本组件的配置中枢包含default默认驱动、enable各调用类型开关、tracer各驱动详细配置、tagsSpan Tag 映射四大部分下文逐一展开。配置详解开启各类调用的 tracing 开关默认情况下组件为 Guzzle HTTP 调用、Redis 调用、DB 调用提供了 AOP 切面用于实现调用链的传播与追踪但这些追踪默认是关闭的。需要打开config/autoload/opentracing.php中enable项按需开启?php return [ enable [ // 是否开启 Guzzle HTTP 调用的链路追踪 guzzle false, // 是否开启 Redis 调用的链路追踪 redis false, // 是否开启 DB 调用的链路追踪 db false, ], ];在官方发布的完整配置中enable还支持更多类型且每个开关都提供了对应的环境变量方便按环境区分enable [ coroutine env(TRACER_ENABLE_COROUTINE, false), // 协程 db env(TRACER_ENABLE_DB, false), // 数据库 elasticserach env(TRACER_ENABLE_ELASTICSERACH, false), // Elasticsearch exception env(TRACER_ENABLE_EXCEPTION, false), // 异常 grpc env(TRACER_ENABLE_GRPC, false), // gRPC guzzle env(TRACER_ENABLE_GUZZLE, false), // Guzzle HTTP method env(TRACER_ENABLE_METHOD, false), // 普通方法Beta redis env(TRACER_ENABLE_REDIS, false), // Redis rpc env(TRACER_ENABLE_RPC, false), // RPC ignore_exceptions [], // 忽略追踪的异常类列表 ],从 SwitchManager.php 的源码可以看到开关的判定逻辑isEnable()除了要求对应配置为true还要求协程上下文中已存在tracer.root根 Span也就是说追踪只会在已开启追踪的请求内部生效避免无谓的开销。此外源码注释明确提示method属于 Beta 功能不建议在生产环境开启。选择默认 Tracer 驱动default的值对应使用的驱动名称驱动具体配置定义在tracer项下以相同名称作为key?php return [ // 选择默认的 Tracer 驱动所选 Tracer 名称需与下方 tracers 中定义的 key 对应 default env(TRACER_DRIVER, staging_zipkin), // 此处省略其他配置 enable [], tracer [ // Zipkin 配置 staging_zipkin [ driver \Hyperf\Tracer\Adapter\ZipkinTracerFactory::class, ], // 另一个 Zipkin 配置 producton_zipkin [ driver \Hyperf\Tracer\Adapter\ZipkinTracerFactory::class, ], // Jaeger 配置 jaeger [ driver \Hyperf\Tracer\Adapter\JaegerTracerFactory::class, ], ] ];注意示例配置中展示了同时配置多个 Zipkin 或 Jaeger 驱动的用法。虽然它们基于同一套后端系统但具体参数可以不同。典型场景是测试环境 100% 采样、生产环境 1% 采样——分别配置两个驱动再通过default项结合环境变量在不同环境切换。这一选择机制在 TracerFactory.php 中落地框架读取opentracing.default得到驱动名再取opentracing.tracer.{name}.driver作为工厂类实例化后调用其make($name)方法生成真正的 OpenTracing Tracer。若驱动类未实现NamedFactoryInterface会抛出InvalidArgumentException提示配置无效。配置 Zipkin使用 Zipkin 时在配置文件的tracer项下添加 Zipkin 专属配置?php use Zipkin\Samplers\BinarySampler; return [ // 选择默认 Tracer default env(TRACER_DRIVER, zipkin), // 演示用不展开 enable 内的配置 enable [], tracer [ // Zipkin 驱动配置 zipkin [ // 当前应用配置 app [ name env(APP_NAME, skeleton), // 若 ipv4 与 ipv6 为空组件将尝试从 Server 自动探测 ipv4 127.0.0.1, ipv6 null, port 9501, ], driver \Hyperf\Tracer\Adapter\ZipkinTracerFactory::class, options [ // Zipkin 服务的 endpoint 地址 endpoint_url env(ZIPKIN_ENDPOINT_URL, http://localhost:9411/api/v2/spans), // 请求超时时间秒 timeout env(ZIPKIN_TIMEOUT, 1), ], // 采样器默认追踪所有请求 sampler BinarySampler::createAsAlwaysSample(), ], ], ];各项配置说明配置项含义默认值app.name当前服务在链路中的名称APP_NAME兜底skeletonapp.ipv4/app.ipv6/app.port服务监听地址与端口用于在链路中标识服务实例127.0.0.1/null/9501options.endpoint_urlZipkin Collector 的 Span 上报地址http://localhost:9411/api/v2/spansoptions.timeout上报请求超时秒1sampler采样器实例需实现Zipkin\Sampler接口全量采样在 ZipkinTracerFactory.php 中可以看到这些配置的消费方式工厂通过Endpoint::create()构建本地端点再由TracingBuilder装配采样器与 Reporter 后产出 OpenTracing Tracer。关于ipv4为空时自动探测文档说明组件会从 Server 自动探测系统信息不过从当前源码看该逻辑仍标注为TODO建议显式配置或依赖环境变量不要完全依赖自动探测。官方发布配置还支持 Zipkin 的多种Reporter上报通道通过reporter字段切换默认httpreporter env(ZIPKIN_REPORTER, http), // kafka, http reporters [ // HTTP 上报 http [ class Http::class, constructor [ options [ endpoint_url env(ZIPKIN_ENDPOINT_URL, http://localhost:9411/api/v2/spans), timeout env(ZIPKIN_TIMEOUT, 1), ], ], ], // Kafka 上报 kafka [ class Kafka::class, constructor [ options [ topic env(ZIPKIN_KAFKA_TOPIC, zipkin), bootstrap_servers env(ZIPKIN_KAFKA_BOOTSTRAP_SERVERS, 127.0.0.1:9092), acks (int) env(ZIPKIN_KAFKA_ACKS, -1), connect_timeout (int) env(ZIPKIN_KAFKA_CONNECT_TIMEOUT, 1), send_timeout (int) env(ZIPKIN_KAFKA_SEND_TIMEOUT, 1), ], ], ], // 空实现不发送 noop [ class Noop::class, ], ],在高并发场景下将 Span 批量投递到 Kafka 再由 Zipkin 消费能有效降低对业务进程的阻塞影响。配置 Jaeger使用 Jaeger 时在tracer项下添加 Jaeger 专属配置?php use Hyperf\Tracer\Adapter\JaegerTracerFactory; use const Jaeger\SAMPLER_TYPE_CONST; return [ // 选择默认 Tracer default env(TRACER_DRIVER, jaeger), // 演示用不展开 enable 内的配置 enable [], tracer [ // Jaeger 驱动配置 jaeger [ driver JaegerTracerFactory::class, // 项目名称 name env(APP_NAME, skeleton), options [ // 采样器默认追踪所有请求 sampler [ type SAMPLER_TYPE_CONST, param true, ], // 上报 Agent local_agent [ reporting_host env(JAEGER_REPORTING_HOST, localhost), reporting_port env(JAEGER_REPORTING_PORT, 5775), ], ], ], ], ];options.sampler用于控制采样策略SAMPLER_TYPE_CONST配合param true表示全量采样local_agent指向 Jaeger Agent 的地址默认 UDP 5775 端口。若需更丰富的 Jaeger 采样策略如按比例采样可以参考jaeger-client-php的配置说明进行扩展官方发布配置中也将 sampler 相关选项注释保留供按需取消注释使用。从 JaegerTracerFactory.php 的源码可以看到工厂把配置包装成Jaeger\Config后调用initializeTracer()完成初始化同时会将项目名与options一一对应到 Tracer 实例。开启 JsonRPC 链路追踪BetaJsonRPC 链路追踪不在统一配置开关中目前属于Beta功能。只需在config/autoload/aspects.php中注册对应切面即可启用?php return [ Hyperf\Tracer\Aspect\JsonRpcAspect::class, ];提示别忘了在对端服务添加相应的 TraceMiddleware否则链路上下文无法在服务间传递。需要说明的是当前仓库 src/tracer/src/Aspect 中与 RPC 相关的切面为RpcAspect.php并同时提供了GrpcAspect.php说明文档中JsonRpcAspect的写法属于较早版本的命名实际使用请以你所安装版本中的切面类名为准无论类名如何变化注册思路与上面完全一致。开启 Coroutine 链路追踪协程链路追踪同样不在统一配置开关中属于可选功能。在config/autoload/aspects.php中注册?php return [ Hyperf\Tracer\Aspect\CoroutineAspect::class, ];注册后enable.coroutine开关配合该切面即可在协程场景下正确维护 Span 上下文避免协程切换导致链路断裂。配置中间件或监听器收集请求信息完成驱动配置后还需要配置中间件或请求周期的事件监听器才能真正开始收集请求信息。两种方式任选其一方式一注册中间件打开config/autoload/middlewares.php在http节点下启用?php declare(strict_types1); return [ http [ \Hyperf\Tracer\Middleware\TraceMiddleware::class, ], ];从 TraceMiddleware.php 的实现看它会在请求进入时通过SpanStarter创建根 Span自动写入协程 ID、请求路径、请求方法、URI、全部请求头等 Tag响应返回后写入response.status_code并把 Trace ID 注入响应头Trace-Id便于前端或日志联调。若开启了exception开关且异常不在ignore_exceptions列表中还会将异常类名、错误码、消息与堆栈写入 Span 并标记errortrue。请求结束时通过defer调用$tracer-flush()上报数据确保 Span 一定被发送。方式二注册监听器打开config/autoload/listeners.php添加监听器?php declare(strict_types1); return [ \Hyperf\Tracer\Listener\RequestTraceListener::class, ];与中间件方案对应RequestTraceListener.php 监听RequestReceived、RequestHandled、RequestTerminated三个 HTTP 服务器事件请求接收时构建根 Span处理完成时注入Trace-Id响应头请求终止时补充响应状态码与异常信息、结束 Span 并flush()。两种方式能力基本等价你可以根据项目对中间件或事件机制的偏好选择其一。自定义 Span Tag 名称Hyperf 自动采集的 Span Tag 名称支持整体重命名。只需在config/autoload/opentracing.php中新增tags配置若配置项存在使用配置值若不存在回退到组件默认值。return [ tags [ // HTTP ClientGuzzle http_client [ http.url http.url, http.method http.method, http.status_code http.status_code, ], // Redis Client redis [ arguments arguments, result result, ], // 数据库客户端hyperf/database db [ db.query db.query, db.statement db.statement, db.query_time db.query_time, ], ] ];官方发布配置中提供了更完整的 Tag 分组可作为自定义的基础模板分组默认 Tag 键说明http_clienthttp.url/http.method/http.status_codeGuzzle 请求redisarguments/resultRedis 命令参数与结果dbdb.query/db.statement/db.query_time/db.engine/db.instance/db.user数据库查询grpcgrpc.request.header/grpc.response.headergRPC 调用rpcrpc.path/rpc.statusRPC 调用exceptionexception.class/exception.code/exception.message/exception.stack_trace异常信息requestrequest.path/request.uri/request.method/request.header请求元信息body 默认注释关闭coroutinecoroutine.id协程 IDresponseresponse.status_code响应状态码body 默认注释关闭底层实现见 SpanTagManager.php组件内置了上述默认 Tag 映射apply()通过array_replace_recursive将你的tags配置与默认值合并get()返回最终采用的 Tag 键名。中间件与各切面在打点前都会经由SpanTagManager::has()/get()读取因此修改tags配置即可全局生效。替换 Sampler 采样器默认采样器会记录所有请求的调用链这对性能有一定影响尤其是内存占用。通常我们只在需要排查时才全量追踪因此需要替换采样器。替换非常简单以 Zipkin 为例只需将配置项opentracing.zipkin.sampler对应的值换成你自己的采样器实例要求该对象实现Zipkin\Sampler接口即可?php // 自定义采样器例如按比例采样 sampler MyRatioSampler::create(...),生产环境推荐按比例采样如 1%测试环境使用全量采样配合前文的多驱动配置 环境变量切换即可实现环境不同、采样策略不同的最佳实践。接入阿里云链路追踪服务当使用阿里云链路追踪服务时由于其服务端同样兼容 Zipkin 协议我们无需更换驱动只需将config/autoload/opentracing.php中的endpoint_url改为对应地域Region的接入地址即可。具体地址请在阿里云链路追踪服务的控制台中获取并按官方帮助文档完成开通与鉴权配置。业务代码零改动即可将 Span 上报到云上链路平台。使用其他 Tracer 驱动OpenTracing 的开放性意味着你可以接入任何兼容该协议的后端。自定义驱动只需要在tracer的driver项中填写一个实现了Hyperf\Tracer\Contract\NamedFactoryInterface的类?php namespace App\Tracer; use Hyperf\Tracer\Contract\NamedFactoryInterface; class CustomTracerFactory implements NamedFactoryInterface { public function make(string $name): \OpenTracing\Tracer { // 根据 $name 读取配置并构建 Tracer 实例 return $customTracer; } }该接口只有一个make方法参数为驱动名称返回值必须是OpenTracing\Tracer实例。如 TracerFactory.php 所示框架会校验工厂类确实实现了该接口否则抛出InvalidArgumentException。写好后在配置中登记tracer [ custom [ driver \App\Tracer\CustomTracerFactory::class, // 自定义驱动所需的其它配置项 ], ],链路上下文传递的运行机制理解 Span 如何在服务间传递是排查链路断裂问题的关键。核心逻辑集中在 SpanStarter.php根 Span 的创建与上下文提取进入请求后组件以TEXT_MAP格式从 HTTP 请求头中extract()上游传入的 SpanContext即trace-id等追踪头若存在则作为child_of父上下文否则创建全新的根 SpanRPC 上下文接力若容器中存在Hyperf\Rpc\Context且其中携带tracer.carrier则优先使用该载体提取上下文这正是 JsonRPC / RPC 场景下链路跨服务续接的实现途径子 Span 的挂载已有根 Span 时新 Span 一律以根 Span 的 Context 为父节点创建从而构成树状调用链。在客户端侧以 HttpClientAspect.php 为例切面织入GuzzleHttp\Client::request与requestAsync开启guzzle开关后通过tracer-inject()将当前 SpanContext 注入请求头再随请求传递到下游服务调用结束后写入http.status_code等 Tag异常时记录错误日志。它还支持在请求options中传入no_aspect true跳过追踪框架内部也用该机制避免requestAsync被重复织入。Redis、DB 等切面遵循同样的开关 → 建 Span → 注入上下文 → 打 Tag → 结束模式。参考资料OpenTracing 规范opentracing.ioZipkin 分布式追踪系统zipkin.ioJaeger 分布式追踪平台jaegertracing.ioDapper —— Google 大规模分布式系统追踪论文中文翻译版建议在阅读本指南后结合 src/tracer 下的源码与测试用例如 TracerFactoryTest.php进一步理解驱动装配与配置解析的细节以便在真实项目中按需裁剪和扩展。赞分享后端Web框架微服务RPC框架异步编程【免费下载链接】hyperf A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.项目地址https://gitcode.com/hyperf/hyperf点击查看免费下载相关推荐Hyperf 调用链路追踪hyperf/tracer实战指南基于 OpenTracing 协议接入 Zipkin 与 JaegerHyperf 调用链路追踪hyperf/tracer实战指南基于 OpenTracing 协议接入 Zipkin 与 Jaeger 本文是 Hyperf后端Web框架微服务RPC框架异步编程Hyperf 调用链追踪Tracer实战指南基于 OpenTracing 对接 Zipkin 与 JaegerHyperf 调用链追踪Tracer实战指南基于 OpenTracing 对接 Zipkin 与 Jaeger 导读 在微服务架构下一个业务请求少则跨越后端Web框架微服务RPC框架异步编程Hyperf 调用链追踪Tracer实战指南基于 OpenTracing 接入 Zipkin 与 JaegerHyperf 调用链追踪Tracer实战指南基于 OpenTracing 接入 Zipkin 与 Jaeger 在微服务架构下一个业务请求往往需要跨越后端微服务上一篇免费一键解决Mac无法写入NTFS硬盘Free-NTFS-for-Mac 完整上手实录下一篇RDKit 贡献实战指南从 Bug 报告、文档撰写到 C/Python 代码提交的完整手册创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考