nginx 作为链路追踪起点探针,需用 $request_id 唯一锚定请求、透传上下文并结构化日志:1. 直接引用内置 $request_id(≥1.11.0);2. 用 map 兜底兼容上游 id;3. 自定义 json 日志含关键字段;4. 后端须承接并延续该 id 形成闭环。

Nginx 本身不执行业务逻辑,无法生成 span 或参与分布式追踪的完整生命周期,但它作为最外层网关,是链路追踪最关键的“起点探针”。实现请求链路追踪与监控,核心不是让 Nginx 做全链路,而是让它稳稳锚定请求身份、可靠透传上下文、结构化记录入口行为,并与后端服务形成闭环。
用 $request_id 做唯一请求锚点
Nginx 1.11.0+ 内置 $request_id 变量,每次请求自动生成 32 位小写十六进制字符串(如 a1b2c3d4e5f678901234567890abcdef),无需 Lua、无需模块、无需额外配置。它稳定、唯一、线程安全,且在重试、子请求等场景下保持一致。
- 执行
nginx -v确认版本 ≥ 1.11.0,旧版本必须统一升级 - 不要在 http/server 块中
set $req $request_id——它天然可用,直接引用即可 - 在 log_format 中显式写入
"$request_id",引号包裹便于日志采集工具解析
把 ID 透传给后端并兜底兼容
仅生成不够,必须确保下游拿到的是同一个 ID,且能应对上游已带 ID 的情况:
-
proxy_set_header X-Request-ID $request_id必须写在location块内,紧邻proxy_pass - 若前端或网关已传
X-Request-ID,用map实现“有则用之、无则生成”:map $http_x_request_id $forwarded_id { "" $request_id; ~^[a-f0-9]{32}$ $http_x_request_id; default $request_id; } - 同时设置
add_header X-Request-ID $forwarded_id always,让客户端也能看到该 ID
增强日志结构,支撑跨服务关联
默认 access_log 缺少关键链路字段,需自定义格式,覆盖入口耗时、真实上游、协议细节:
- 包含
$request_id、$upstream_addr、$upstream_response_time、$request_time、$status - 推荐 JSON 格式或带明确标识的文本格式,例如:
log_format trace '{"time":"$time_iso8601","req_id":"$request_id","upstream":"$upstream_addr","rt":$request_time,"urt":$upstream_response_time,"status":$status,"path":"$request_uri"}'; - 日志输出到文件或 syslog,接入 Loki / Fluentd / Logstash 做结构化解析和 request_id 聚合
与后端协同,形成完整闭环
Nginx 的工作只到第一跳,后续链路依赖后端主动承接:
- 后端服务(Spring Boot / Go / Node.js)需从
X-Request-ID读取值,注入 MDC、Zap 字段或 OpenTelemetry context - 下游调用时,将该 ID 作为
trace-id或X-Request-ID继续透传,保持格式统一(如始终 32 位小写 hex) - 若使用 Jaeger / Zipkin / OTel,可将
$request_id作为 trace ID 的基础值(需适配器映射,不直接等价但可 fallback)
不复杂但容易忽略











