7.1.6 请求处理流程与阶段(phases)
请求处理流程与阶段(phases)#
Nginx 的请求处理由阶段(phases)驱动,各阶段由不同类型模块挂载处理器,按固定顺序执行,实现从接收请求到响应输出的完整流水线。理解 phases 有助于定位请求被哪类模块接管、为何会被改写或终止。
原理草图(请求与阶段)
主要阶段与典型模块
- post-read:请求读取完成后触发,少量模块使用。
- server-rewrite / rewrite:执行 rewrite、if 等重写规则,可能触发内部重定向。
- find-config:location 匹配完成,确定最终配置上下文。
- preaccess / access:访问控制与认证,如 allow/deny、auth_basic、limit_conn/limit_req。
- try-files:根据文件存在性选择资源或内部跳转。
- content:内容生成阶段,反向代理、静态文件、FastCGI、uwsgi、gRPC 等在此提供响应。
- log:记录访问日志与统计。
安装与环境准备(示例)
# Debian/Ubuntu
sudo apt update
sudo apt install -y nginx
# RHEL/CentOS
sudo yum install -y nginx
# 启动与开机自启
sudo systemctl enable --now nginx
示例:用 rewrite + access + content 观察阶段行为
- 文件路径:/etc/nginx/conf.d/phases.conf
server {
listen 8080;
server_name localhost;
access_log /var/log/nginx/phases.access.log main;
error_log /var/log/nginx/phases.error.log debug;
# rewrite 阶段:将 /old -> /new
location = /old {
rewrite ^ /new last;
}
# access 阶段:只允许本机访问 /admin
location /admin {
allow 127.0.0.1;
deny all;
return 200 "admin ok\n";
}
# try_files + content 阶段:先找静态文件,否则走反向代理
location / {
root /var/www/html;
try_files $uri @backend;
}
location @backend {
proxy_pass http://127.0.0.1:9000;
proxy_set_header Host $host;
}
# content 阶段:提供 /new 内容
location = /new {
return 200 "rewrite hit\n";
}
}
启动测试后端与验证
# 启动一个简易后端(Python)
python3 -m http.server 9000
# 重新加载 Nginx
sudo nginx -t
sudo systemctl reload nginx
# 验证 rewrite 阶段
curl -i http://127.0.0.1:8080/old
# 验证 access 阶段(非本机将返回 403)
curl -i http://127.0.0.1:8080/admin
# 验证 try_files + 反向代理
curl -i http://127.0.0.1:8080/
命令与关键参数解释
- nginx -t:语法检查配置,避免 reload 后服务不可用。
- systemctl reload nginx:平滑重载,不中断已有连接。
- error_log ... debug:输出阶段执行细节,便于观察内部重定向与处理器链。
- try_files $uri @backend:先找静态文件,不存在则进入命名 location(content 阶段的代理模块)。
常见排错思路(带命令)
1. 重写异常或循环
bash
# 观察 debug 日志中的 rewrite/internal redirect
sudo tail -f /var/log/nginx/phases.error.log
关注是否多次出现 rewrite 或 internal redirect,必要时改用 break 或调整正则。
-
访问被拒绝
bash curl -i http://127.0.0.1:8080/admin
若返回 403/401,检查access阶段配置(allow/deny、auth_basic、limit_req)。 -
代理不生效
bash # 判断是否命中静态文件或被其他 location 截获 curl -i http://127.0.0.1:8080/ -H "Host: localhost"
确认try_files路径与root是否正确,以及命名 location 是否被调用。
练习
1. 将 /old 的 rewrite 改为 rewrite ^ /new break;,比较 last 与 break 的差异。
2. 在 location / 中添加 limit_req,观察 access 阶段限流对响应码的影响。
3. 打开/关闭 error_log debug,对比日志中是否能看到阶段与内部重定向路径。