nginx指令执行顺序由配置块嵌套层级、location匹配规则和请求处理阶段三重机制共同决定:作用域控制继承与覆盖,location按类型优先级及定义顺序匹配,各阶段指令严格按11个处理阶段串行执行。

Nginx 中 nginx.conf 指令的“执行顺序”并非字面意义的从上到下逐行运行,而是由三重机制共同决定:配置块的嵌套层级(作用域)、location 匹配规则、以及请求处理阶段(phase)。真正影响最终行为的,是这三者如何协同工作,而非单纯看配置文件里哪行写在前面。
配置块层级决定作用域与继承关系
指令生效范围严格受限于其所在上下文(context),比如 worker_processes 只能在 main 块使用,放在 http 或 server 块中会直接启动失败;root 在 server 块中定义后,其下的 location 可用 root 或 alias 覆盖路径映射。同一作用域内重复出现的可覆盖指令(如 root、add_header),后定义的值会生效;但不可重复指令(如 listen)在同一 server 块中重复将报错。
- 高一级块中的指令默认向下继承,低一级块中同名指令优先级更高(就近原则)
- server 块之间不按书写顺序匹配,而是构建匹配树:精确 server_name > 前缀通配符 > 后缀通配符 > default_server
- include 是预处理展开,其位置决定了被引入内容所处的上下文——误放在 server 块里的 mime.types 会导致语法错误
location 匹配依赖定义顺序与类型优先级
location 的选择发生在请求到达时,但正则表达式(~、~*)的匹配顺序完全取决于它们在配置文件中出现的物理顺序:Nginx 从上到下依次尝试,一旦匹配成功即停止。而前缀匹配(=、^~、普通字符串)则先找出最长前缀,再判断是否含 ^~ 或 = ——若含 ^~ 且为最长前缀,则跳过所有正则检查。
- 更具体的正则必须写在更宽泛的正则之前,否则会被提前截断(例如
~ \.php$必须放在~ ^/admin/.*\.php$后面才可能生效) - = 优先级最高,用于绝对路径精确匹配;^~ 用于禁止后续正则检查,适合静态资源路径
- 普通前缀匹配区分大小写,但不支持正则语法;~* 则不区分大小写,适合忽略大小写的扩展名控制
请求处理阶段决定指令实际运行时序
即使指令写在同一 location 块中,它们也可能在完全不同的阶段执行。Nginx 将请求划分为 11 个处理阶段,各模块指令注册在特定阶段,阶段之间不可交错。例如:set 属于 rewrite 阶段,echo 属于 content 阶段,因此无论配置中怎么排列,所有 set 总是在所有 echo 之前执行。
- rewrite 阶段:处理 URL 重写、变量赋值(set)、条件判断(if)等
- access 阶段:权限控制(allow/deny)、限流(limit_req)等
- content 阶段:生成响应内容(proxy_pass、fastcgi_pass、echo 等)
- 同一阶段内的指令按配置顺序执行;跨阶段指令严格按阶段顺序串行执行
include 文件顺序直接影响指令可见性与覆盖逻辑
include 不是动态加载,而是配置解析期的文本展开。它把外部文件内容原样插入当前位置,因此 include 的物理顺序决定了指令注入的时机和上下文。
- 先 include upstreams.conf,再定义 server,才能在 server 中引用其中的 upstream 名称
- 多个 include 引入相同指令(如多个 add_header),后 include 的会覆盖先 include 的(若指令支持覆盖)
- 若 a.conf 定义了某个 server_name,b.conf 又定义了同端口的 server 块且含 default_server,则后者会成为默认虚拟主机











