Nginx、Caddy、Apache 如何生成 Request ID?

在 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 实现完整的分布式链路追踪。

如果你有魔法,你可以看到一个评论框~