nginx 默认不记录子请求,需启用 log_subrequest on 并配合含 $request_id、$subrequest 等字段的日志格式才能完整追踪主/子请求链路。

Nginx 默认不记录内部重定向(如 rewrite last、try_files fallback、auth_request、SSI include、ngx.location.capture 等)产生的子请求,因为它们是服务器内部发起的,不经过完整网络栈。要完整还原一次用户请求触发的全部执行轨迹——包括主请求、内部跳转、缓存兜底、嵌套片段加载——必须启用并配置 log_subrequest 机制。
开启 log_subrequest 记录子请求
该指令自 Nginx 1.19.2 起稳定可用(推荐 ≥1.21.0),需显式启用才生效:
- 放在
http、server或location块中(注意:不继承,子块需单独设) - 必须置于
access_log指令之后或同级作用域,否则无效 - 值为
on(默认是off) - 示例:
log_subrequest on;
定义能区分主/子请求的日志格式
仅开 log_subrequest on 不够,日志格式必须包含可识别字段:
-
$request_completion:主请求为OK,子请求为subrequest(推荐) -
$subrequest:子请求中值为"1",主请求为空 -
$request_id:同一客户端请求及其所有子请求共享该 ID,是链路追踪核心锚点(需 Nginx ≥1.11.0) - 补充字段如
$upstream_cache_status、$uri、$request_time可辅助判断缓存行为与路径变化
典型格式示例:
log_format trace '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' 'req_id="$request_id" sub="$subrequest" cache="$upstream_cache_status" rt=$request_time';access_log /var/log/nginx/trace.log trace;
识别日志中的内部请求轨迹
启用后,一次含 SSI 或 `try_files` 的请求会在日志中出现多条记录,可通过以下特征关联分析:
- 所有记录的
req_id完全一致 → 属于同一次用户请求 - 主请求
sub=" ",子请求sub="1"(或request_completion="subrequest") - 子请求的
$request多为内部路径(如"GET /_header.html HTTP/1.0"),协议常为 HTTP/1.0 - 子请求的
$remote_addr可能为127.0.0.1或空,$status可能是 200(内容被嵌入)、404(fallback 失败)或 302(内部重定向未终止)
配合 debug 日志定位循环问题
若怀疑内部重定向陷入循环(报 500 错误),仅 access 日志不够,还需:
- 临时启用
error_log /var/log/nginx/error.log debug;(确认编译含--with-debug) - 在 error.log 中搜索
rewrite phase、internal redirecting to,查看逐跳路径 - 对高风险 location 单独加 access_log,例如:
access_log /var/log/nginx/redirect.log main if=$log_redirect;,配合map标记关键路径











