ThinkPHP链路追踪采样率需自行实现,应在中间件入口用请求特征哈希(如crc32($uri)%100)做一致性采样,避免rand;禁用SkyWalking自动注入,白名单过滤高频接口,动态策略建议通过Redis热更新。

ThinkPHP 接口调用链路追踪怎么设采样率
ThinkPHP 本身不内置分布式链路追踪(如 OpenTracing / OpenTelemetry),所谓“采样率”必须靠你接入的 APM 工具(比如 SkyWalking、Jaeger、Zipkin 或自研埋点)来控制。框架层只提供钩子和中间件能力,采样逻辑得你自己写——不是配个 config 就生效。
常见错误是直接在 app/middleware/TraceMiddleware.php 里无条件创建 span,结果高流量下打满日志或压垮上报服务。
- 采样决策必须在请求入口就做,避免后续资源浪费(如 DB 查询、HTTP 调用已执行才丢弃 trace)
- 不要在
__destruct或响应后才判断是否上报,span 生命周期可能已结束 - ThinkPHP 6+ 的中间件执行顺序要确认是否在路由解析之后(否则拿不到
$request->action()等关键信息)
如何在中间件里实现按比例采样(例如 1%)
核心是:用请求特征(如 URL、Header、用户 ID)做一致性哈希,再对固定模数取余。这样相同请求路径大概率被稳定采样,便于问题复现,又不会随机抖动导致漏掉关键链路。
示例代码片段(放在中间件 handle 方法开头):
立即学习“PHP免费学习笔记(深入)”;
$uri = $request->url();
$hash = abs(crc32($uri)) % 100;
if ($hash >= 1) { // 1% 采样
return $next($request);
}
// 启动 trace,创建 root span...
- 别用
rand(0,99)—— 每次请求都新生成,无法保证同一接口的复现性 - 如果想按用户采样(如只追踪 VIP 用户),可用
$request->header('x-user-id')参与哈希,但注意 header 可能为空 - 模数选 100 是为了方便配置百分比;若需 0.1%,建议用
% 1000+ 判断< 1
ThinkPHP 与 SkyWalking Agent 共存时采样冲突怎么办
SkyWalking PHP Agent(如 skywalking-php)默认全量采集,会覆盖你在中间件里的采样逻辑,且无法通过环境变量关掉自动 trace。这时候你的中间件采样只是“多做一层无效过滤”,反而增加开销。
- 必须关闭 Agent 的自动注入:设置
SW_AGENT_DISABLE=1,改用手动 SDK(如OpenTracing\GlobalTracer::get())控制 span 创建 - Agent 的
SW_AGENT_SAMPLE_RATE配置仅作用于其内置采样器,对 ThinkPHP 中间件无影响 - 验证是否生效:看 SkyWalking UI 里 trace 列表数量是否明显下降,同时检查日志中是否有
SpanContext not found类报错(说明手动 tracer 未正确初始化)
高频接口(如心跳 / 健康检查)如何彻底跳过追踪
这类请求本就不该进链路系统——它们没有业务语义,纯属基础设施噪声。硬靠采样率(比如 0.01%)仍可能每天刷出几百条无效 trace。
- 在中间件最开头加白名单拦截:
if (in_array($request->path(), ['ping', 'healthz', 'favicon.ico'])) return $next($request); - 别依赖控制器方法名(如
IndexController@ping),因为路由可能重写,path 更可靠 - ThinkPHP 的
$request->isOptions()或$request->isHead()也可作为轻量请求标识,配合使用
真正难的是动态策略:比如某接口突然错误率飙升,临时提高它的采样率。这需要把采样逻辑抽成可热更的服务(如 Redis 读配置),而不是写死在代码里。


















