如何通过Nginx log_subrequest功能详细记录SSI或镜像子请求的运行细节?
- 内容介绍
- 文章标签
- 相关推荐
本文共计824个文字,预计阅读时间需要4分钟。
使用 `log_subrequest` 指令可以使得 Nginx 在 access log 中记录子请求(subrequest)的访问信息,这对于调试 SSI(Server Side Includes)、`mirror` 指令、`auth_request` 指令或自定义模块的内部请求非常有用。默认情况下,这些子请求不会出现在 access log 中,可能导致日志信息缺失或链路不完整。
确认 Nginx 版本与编译支持
该指令自 Nginx 1.19.1 起正式引入,且需确保使用的是官方主线版本或较新稳定版(如 1.20+)。OpenResty 等衍生版本通常也支持,但建议先验证:
- 运行
nginx -V 2>&1 | grep -o 'nginx version: nginx/[^ ]*'查看版本 - 检查输出中是否含
--with-http_subrequest_module(通常默认内置,无需额外编译) - 若为旧版(如 1.18 或更早),升级是必要前提
在 log_format 中添加 $request_id 和 $subrequest 变量
仅开启 log_subrequest on 不够,还需在日志格式中显式引用子请求标识变量,否则日志无法区分主/子请求:
-
$request_id:配合ngx_http_core_module的request_id指令,为每个请求(含子请求)生成唯一 ID,便于关联追踪 -
$subrequest:Nginx 内置变量,主请求为0,子请求为1,是识别子请求最直接依据 - 推荐日志格式示例:
log_format detailed '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_id $subrequest';
全局或 location 级别启用 log_subrequest
该指令作用域为 http、server 或 location,按需启用即可,无需重启整个服务(reload 生效):
- 全局启用(影响所有子请求):
http {<br> log_subrequest on;<br> log_format ...;<br> access_log /var/log/nginx/access.log detailed;<br>}
- 仅对 SSI 启用(推荐,减少日志冗余):
location /includes/ {<br> ssi on;<br> log_subrequest on;<br> access_log /var/log/nginx/ssi.log detailed;<br>}
- 镜像请求场景下,常配合
mirror使用,此时也应将log_subrequest on放在 mirror 所在 location 块内
结合 SSI 或 mirror 验证日志输出
配置生效后,可通过实际请求观察日志是否包含子请求条目:
- SSI 示例:页面中含
<!--# include file="/includes/header.html" -->,访问该页面时,日志中会出现两条记录——主请求($subrequest 0)和 header.html 的子请求($subrequest 1),两者$request_id相同 - Mirror 示例:启用
mirror /mirror;后,主请求日志旁会多出一条POST /mirror记录,$subrequest 1,状态码通常为200或404(取决于 mirror 后端响应) - 注意:子请求的
$request_time和$upstream_response_time是独立统计的,可用于分析 SSI 包含耗时或 mirror 延迟
本文共计824个文字,预计阅读时间需要4分钟。
使用 `log_subrequest` 指令可以使得 Nginx 在 access log 中记录子请求(subrequest)的访问信息,这对于调试 SSI(Server Side Includes)、`mirror` 指令、`auth_request` 指令或自定义模块的内部请求非常有用。默认情况下,这些子请求不会出现在 access log 中,可能导致日志信息缺失或链路不完整。
确认 Nginx 版本与编译支持
该指令自 Nginx 1.19.1 起正式引入,且需确保使用的是官方主线版本或较新稳定版(如 1.20+)。OpenResty 等衍生版本通常也支持,但建议先验证:
- 运行
nginx -V 2>&1 | grep -o 'nginx version: nginx/[^ ]*'查看版本 - 检查输出中是否含
--with-http_subrequest_module(通常默认内置,无需额外编译) - 若为旧版(如 1.18 或更早),升级是必要前提
在 log_format 中添加 $request_id 和 $subrequest 变量
仅开启 log_subrequest on 不够,还需在日志格式中显式引用子请求标识变量,否则日志无法区分主/子请求:
-
$request_id:配合ngx_http_core_module的request_id指令,为每个请求(含子请求)生成唯一 ID,便于关联追踪 -
$subrequest:Nginx 内置变量,主请求为0,子请求为1,是识别子请求最直接依据 - 推荐日志格式示例:
log_format detailed '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_id $subrequest';
全局或 location 级别启用 log_subrequest
该指令作用域为 http、server 或 location,按需启用即可,无需重启整个服务(reload 生效):
- 全局启用(影响所有子请求):
http {<br> log_subrequest on;<br> log_format ...;<br> access_log /var/log/nginx/access.log detailed;<br>}
- 仅对 SSI 启用(推荐,减少日志冗余):
location /includes/ {<br> ssi on;<br> log_subrequest on;<br> access_log /var/log/nginx/ssi.log detailed;<br>}
- 镜像请求场景下,常配合
mirror使用,此时也应将log_subrequest on放在 mirror 所在 location 块内
结合 SSI 或 mirror 验证日志输出
配置生效后,可通过实际请求观察日志是否包含子请求条目:
- SSI 示例:页面中含
<!--# include file="/includes/header.html" -->,访问该页面时,日志中会出现两条记录——主请求($subrequest 0)和 header.html 的子请求($subrequest 1),两者$request_id相同 - Mirror 示例:启用
mirror /mirror;后,主请求日志旁会多出一条POST /mirror记录,$subrequest 1,状态码通常为200或404(取决于 mirror 后端响应) - 注意:子请求的
$request_time和$upstream_response_time是独立统计的,可用于分析 SSI 包含耗时或 mirror 延迟

