在 Web 服务排查问题时,经常需要根据一个请求 ID,关联反向代理日志和后端应用日志。Nginx 内置了 $request_id,可以自动生成请求唯一标识。那么 Caddy 和 Apache 是否也支持类似功能?
1. Nginx
Nginx 从 1.11.0 开始提供 $request_id 变量,使用 16 字节随机数据生成 32 位十六进制字符串。
http {
log_format main
'$remote_addr "$request" $status '
'request_id=$request_id';
server {
listen 80;
add_header X-Request-ID $request_id always;
location / {
proxy_pass http://backend;
proxy_set_header X-Request-ID $request_id;
}
}
}
通过 add_header 将 ID 返回给客户端,通过 proxy_set_header 传递给后端,同时在 Access Log 中记录,方便关联排查。
2. Caddy
Caddy 提供 {http.request.uuid} 占位符,可以生成当前请求的 UUID。
example.com {
log
log_append request_id {http.request.uuid}
header X-Request-ID {http.request.uuid}
reverse_proxy localhost:8080 {
header_up X-Request-ID {http.request.uuid}
}
}
其中 log_append 用于将请求 ID 写入 Access Log,header 设置响应头,header_up 将 ID 传递给后端。
3. Apache
Apache 有两种相关机制。
mod_unique_id:启用后,为每个请求生成唯一标识,存储在环境变量 UNIQUE_ID 中。
sudo a2enmod unique_id headers
配置日志及后端请求头:
LogFormat "%h %t \"%r\" %>s %{UNIQUE_ID}e" with_id
CustomLog ${APACHE_LOG_DIR}/access.log with_id
RequestHeader set X-Request-ID "%{UNIQUE_ID}e"
Header always set X-Request-ID "%{UNIQUE_ID}e"
%L 日志变量:Apache 2.4 还提供 %L,用于关联 Access Log 和 Error Log。它主要用于 Apache 内部日志关联,不等同于跨服务传递的请求 ID。
4. 工程实践建议
三种 Web Server 都具备请求标识能力,建议统一采用 X-Request-ID 请求头:
- 入口代理生成请求 ID,不直接信任外部客户端传入的 ID。
- 多层代理之间持续透传,不重复生成。
- 后端 Go、Python 等服务将 ID 注入日志上下文。
- 响应头返回 ID,方便客户端反馈问题时提供排查线索。
需要注意,Request ID 解决的是单次请求的日志关联问题。如果涉及跨服务调用、异步任务和复杂调用链,建议进一步采用 W3C Trace Context(traceparent)标准,配合 OpenTelemetry 实现完整的分布式链路追踪。