要让nginx显式记录请求实际经过的处理阶段顺序,需通过log_format自定义日志+变量注入+各阶段可写变量支持:先用set或lua在关键阶段标记$phase_trace,再在log_by_lua_block中统一输出,最终在access_log中显示完整阶段轨迹。

要让 Nginx 显式记录请求实际经过的处理阶段顺序,不能靠默认日志,需结合 log_format 自定义日志字段 + 变量注入 + 各阶段可写变量的模块支持。核心思路是:在关键阶段用 set 或 lua 标记当前阶段,最后统一输出到 access_log。
启用阶段标记变量(基础方式)
Nginx 本身不提供内置变量表示“当前所处阶段”,但可通过以下方式间接实现:
- 使用
ngx_http_set_misc_module的set_by_lua在每个阶段末尾追加阶段名到一个临时变量(如$phase_trace) - 或更轻量:在各阶段中用
set指令覆盖/拼接变量(注意:rewrite 阶段前变量不可写,需从rewrite开始) - 例如,在 location 块中按顺序写入:
set $phase_trace "start"; rewrite ^(.*)$ $1 break; # 触发 rewrite 阶段 set $phase_trace "${phase_trace}→rewrite"; access_by_lua 'ngx.var.phase_trace = ngx.var.phase_trace .. "→access"'; set $phase_trace "${phase_trace}→tryfiles"; try_files $uri $uri/ /index.html;
定义带阶段轨迹的日志格式
在 http 块中添加:
log_format trace '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'phases="$phase_trace"';
然后在 server 或 location 中启用:access_log /var/log/nginx/access-trace.log trace;
这样每条日志末尾会显示类似:phases="start→rewrite→access→tryfiles→content"
用 Lua 精确捕获全部 11 个阶段(推荐)
安装 nginx-module-lua 后,可在不同阶段注册钩子:
-
init_by_lua_block:初始化全局变量 -
rewrite_by_lua_block:在 rewrite 阶段末尾追加 -
access_by_lua_block:在 access 阶段追加 -
content_by_lua_block:在 content 阶段追加(注意:此处不能再改响应头) -
log_by_lua_block:在 log 阶段统一输出,最可靠 —— 所有前面阶段的标记都已就绪
示例配置片段:
set $phase_trace "";
log_by_lua_block {
ngx.var.phase_trace = string.gsub(ngx.var.phase_trace, "^→", "");
ngx.log(ngx.INFO, "TRACE: ", ngx.var.phase_trace);
}
rewrite_by_lua_block { ngx.var.phase_trace = ngx.var.phase_trace .. "→rewrite" }
access_by_lua_block { ngx.var.phase_trace = ngx.var.phase_trace .. "→access" }
content_by_lua_block { ngx.var.phase_trace = ngx.var.phase_trace .. "→content" }
验证阶段执行路径的实用技巧
不依赖日志也能快速确认流程:
- 在某个 location 中只配
return 200 "from content";→ 可确认是否走到 content 阶段 - 加
deny all;并访问 → 若返回 403,说明 access 阶段生效;若仍能访问,说明被更高优先级规则跳过或未命中该 location - 用
try_files /nonexist @fallback;+location @fallback { return 200 "fallback"; }→ 可验证 try-files 是否触发 fallback - 配合
error_log /path debug;查看 debug 日志(需编译含 --with-debug),Nginx 会在内部打印各阶段进入/退出信息











