全链路追踪可跨二级域名,关键在于traceparent等请求头的完整传递与透传;需前端开启credentials、后端配置cors放行、反向代理不过滤header,并在thinkphp中统一提取和复用上下文。

ThinkPHP 本身不支持二级域名自动透传链路上下文,全链路追踪能否跨二级域名,关键不在域名配置本身,而在于请求头是否完整传递 trace 上下文。只要 HTTP 请求中携带 traceparent(或你自定义的 X-Trace-ID 等字段),SkyWalking 就能串联起不同二级域名下的服务调用。
二级域名不影响链路,但跨域请求常丢失 header
常见误区是认为“二级域名不同 = 链路断开”,其实真正导致链路断裂的是:前端发起跨域请求时未设置 credentials: 'include',或后端未正确响应 Access-Control-Allow-Headers,导致 traceparent 等关键 header 被浏览器拦截丢弃。
- 前端 Axios/Fetch 发起请求时,必须显式开启凭据:
credentials: 'include' - ThinkPHP 的 CORS 中间件需放行追踪字段,例如在
app/middleware/CorsMiddleware.php中添加:header('Access-Control-Allow-Headers: traceparent, X-Trace-ID, X-User-ID'); - 确保 Nginx/Apache 反向代理未过滤或重写这些 header(检查
proxy_pass_request_headers on;和underscores_in_headers on;)
ThinkPHP 多子域统一 trace 上下文管理
若你的业务涉及 api.example.com、admin.example.com、pay.example.com 等多个二级域名,且它们同属一个 ThinkPHP 应用(通过 request.domain 判断路由),建议在入口中间件中统一提取并复用上下文,避免各子域各自生成新 trace_id。
- 在
TraceMiddleware::handle()开头,优先从$_SERVER['HTTP_TRACEPARENT']提取;无则 fallback 到$_SERVER['HTTP_X_TRACE_ID']或自动生成 - 将解析后的
TraceContext存入think\facade\Request::withAttribute('trace_context', $ctx),供后续所有子域逻辑复用 - DB/Redis/HTTP 客户端中间件统一从该 attribute 读取,而非重新解析 header
跨二级域名调用时手动注入 header
当 ThinkPHP 后端主动调用另一个二级域名的服务(如 api.example.com 调 pay.example.com),必须显式透传上下文。不能依赖全局 HttpClient 单例,必须每次调用前构造带 header 的实例:
- 使用
think\HttpClient::create()->withHeaders($headers)->get($url) -
$headers至少包含:['traceparent' => $currentSpan->getContext()->getTraceParent()](OpenTelemetry SDK 方式)或['X-Trace-ID' => $traceId](简易方式) - 若调用封装在 Service 类中,务必把
$traceId和$spanContext作为参数传入,禁止在 Service 内部重新生成
SkyWalking UI 中验证多域名链路是否连通
部署完成后,在 SkyWalking UI(http://skywalking-ui:8080)中验证是否真正打通:
- 进入「拓扑图」查看
api.example.com、pay.example.com是否出现在同一张图中,并有连线 - 搜索任意一次请求的
trace_id,确认其 span 分布在多个服务名下(服务名应配置为api-service、pay-service,而非域名) - 点开 trace 详情,检查每个 span 的
parent_span_id是否逐级嵌套,且service字段准确对应各子域后端服务标识
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











