Nginx 中 $request_id 是实现分布式链路追踪染色的基础,自1.11.0起默认启用UUIDv4格式唯一标识,需确保版本兼容并透传至后端服务。

在 Nginx 中通过 log_format 引入 $request_id,是实现跨系统分布式链路追踪“染色”的基础一步。它的核心作用是:为每个进入 Nginx 的请求生成唯一标识,并将其透传至后端服务(如 Go/Java 服务),从而让日志、监控、APM 工具能将一次完整调用链(Nginx → API 网关 → 微服务 A → 微服务 B)串联起来。
确保 $request_id 可用且稳定生成
Nginx 自带的 $request_id 变量从 1.11.0 版本起默认启用,它基于随机数生成 UUIDv4(格式如 9b5e8a2f-1c3d-4e5f-8a7b-123456789abc)。但需注意:
- 若使用较老版本 Nginx(map +
random模块模拟(不推荐,稳定性差) - 该变量在请求生命周期内始终存在,包括重试、子请求(subrequest)中也保持一致,适合做链路锚点
- 无需额外模块,开箱即用,但需确认配置中未被覆盖或清空(例如某些 Lua 脚本误设为空)
在 log_format 中嵌入 $request_id 并输出到访问日志
定义一个含 $request_id 的日志格式,便于后续日志采集与解析:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_id ' # ← 关键:加入 request_id
'$upstream_http_x_request_id '; # ← 可选:透传下游返回的 ID(用于比对)
然后在 server 或 http 块中启用:
access_log /var/log/nginx/access.log main;
这样每条 access 日志末尾都会带上当前请求的唯一 ID,成为链路追踪的第一环“染色标记”。
将 $request_id 透传给后端服务(完成染色传递)
仅记录 ID 不够,必须让后端服务也拿到并使用它。常见方式是通过 HTTP Header 透传:
- 在 proxy_pass 场景中,添加
proxy_set_header X-Request-ID $request_id; - 若后端服务已支持
X-Request-ID(如 Spring Cloud Sleuth、OpenTelemetry SDK、GIN 中间件等),它会自动继承该 ID 并用于打日志、上报 trace - 若后端未主动读取,需在代码中显式获取 header 并注入 logger context 或 trace context(例如 Java 中
MDC.put("requestId", request.getHeader("X-Request-ID")))
注意:避免重复生成 ID。建议所有中间层(Nginx、网关、服务)都优先使用上游传来的 X-Request-ID;只有最上游(如 Nginx)无此 header 时才生成新 ID —— 这可通过 map 实现:
map $http_x_request_id $req_id {
"" $request_id; # 若 header 为空,用 Nginx 自带 ID
default $http_x_request_id; # 否则沿用上游传入的
}
log_format main ... '$req_id';
proxy_set_header X-Request-ID $req_id;
与后端链路系统对齐(关键收尾动作)
光有 $request_id 不代表链路就通了,还需后端配合:
- 确保后端日志框架(Logback、Zap、Pino 等)将
X-Request-ID写入每条日志字段(非仅 message),方便 ELK / Loki 按字段聚合 - 若使用 OpenTelemetry 或 Jaeger,需确认 trace ID 与
request_id对齐 —— 可配置 SDK 将X-Request-ID作为 trace ID 种子(部分 SDK 支持) - 前端发起请求时,也可由 JS 生成并带上
X-Request-ID(用于首屏埋点关联),此时 Nginx 应优先信任该值(见上文map示例)
最终效果:一条用户请求,在 Nginx 日志、API 网关日志、订单服务日志、支付服务日志中,都能用同一个 request_id 精准筛选出全链路行为,快速定位超时、错误、慢 SQL 所在环节。










