请求 ID

OxPHP 处理的每个请求都会获得一个唯一标识符,用于追踪和日志关联。该 ID 会出现在响应头和访问日志中,因此你只需一个值就能在技术栈的每一层追踪同一个请求。

工作原理

OxPHP 会在其他一切逻辑运行之前,先为每个进入的请求分配一个 ID。如果客户端已经发送了 X-Request-ID 头(比如来自负载均衡器或 API 网关),OxPHP 会校验该值并沿用它。要通过校验,请求头长度必须为 1–64 个字符,且只能包含字母数字、连字符(-)、下划线(_)或点号(.)。任何未通过校验的值都会被替换为一个新生成的 ID。

当没有收到有效的 X-Request-ID 时,OxPHP 会生成一个 20 个字符的小写十六进制 ID,例如 67890abc12341a2b0042。该值编码了一个时间戳、一个进程唯一值和一个单调递增计数器,因此跨容器和跨重启发生冲突的可能性极低。

从此之后,这个 ID 便会随请求一路传递:

  • 它会随每个响应通过 X-Request-ID 响应头发出。
  • 启用访问日志后,它会出现在每条访问日志记录的 request_id 字段中。
  • PHP 脚本可以通过 oxphp_request_id() 读取它。

响应头

OxPHP 的每个 HTTP 响应都包含 X-Request-ID 头:

http
HTTP/1.1 200 OK X-Request-ID: 67890abc12341a2b0042 Content-Type: text/html; charset=utf-8

当上游负载均衡器或网关在进入的请求上提供了 X-Request-ID 时,OxPHP 会在响应中原样回传相同的值,从而在你的整个基础设施中实现端到端的可追踪性。

在 PHP 中读取请求 ID

使用 oxphp_request_id() 读取当前的请求 ID:

php
<?php $requestId = oxphp_request_id(); // Include in application logs for correlation $logger->info('Processing order', [ 'request_id' => $requestId, 'order_id' => $orderId, ]);

将请求 ID 转发给下游服务,以在各个 API 调用之间保持可追踪性:

php
<?php $requestId = oxphp_request_id(); $ch = curl_init('https://api.example.com/users'); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "X-Request-ID: $requestId", ]); $response = curl_exec($ch); curl_close($ch);

访问日志记录

启用访问日志后,每条日志记录都包含 request_id 字段:

json
{ "timestamp": "2026-02-11T12:34:56.789Z", "level": "INFO", "fields": { "request_id": "67890abc12341a2b0042", "method": "GET", "path": "/api/users", "status": 200, "duration_us": 1234, "remote_ip": "10.0.0.1", "message": "request completed" } }

在你的日志聚合工具中按 request_id 过滤,即可追踪单个请求的完整生命周期,包括任何引用了同一 ID 的 PHP 错误或应用日志记录。

故障排查

响应中缺少 `X-Request-ID` 头

这是意料之外的情况。OxPHP 会为每个响应都添加该头,因此如果它缺失了,很可能是某个中间代理把它剥离了。

检查方法: 在路径中不经过任何代理的情况下,直接对 OxPHP 进行测试:

bash
curl -v http://localhost:8080/ 2>&1 | grep -i x-request-id
上游的 ID 没有被保留

进入的 X-Request-ID 值可能未通过校验。OxPHP 会拒绝为空、长度超过 64 个字符,或包含字母数字、连字符、下划线、点号以外字符的 ID。

检查方法: 检查上游发送的值,确认它满足字符和长度要求。常见的失败原因包括值中含有斜杠、空格或花括号字符。

`oxphp_request_id()` 返回空字符串

该函数仅在 OxPHP 中可用。如果你在 PHP-FPM 或 CLI 下运行相同的 PHP 代码,这个函数是未定义的。请用兼容性检查来保护对它的调用:

php
<?php $requestId = function_exists('oxphp_request_id') ? oxphp_request_id() : ($_SERVER['HTTP_X_REQUEST_ID'] ?? uniqid('', true));

参见

  • 访问日志 — 每条日志记录都包含 request_id 字段
  • PHP 函数oxphp_request_id() 及其他内置函数的完整参考