目的: '梳理'出来,便于了解'后续'的理解和记忆,本篇大多是'原理'描述
强调: 请求'处理的顺序'和配置文件中的'配置指令'的先后顺序'无关',不要有'先入为主'的错觉
一 nginx的11个阶段
++++++++++++ "nginx为什么是高度模块化?" ++++++++++++
1)nginx将一个'HTTP请求'分成'多个阶段',以'模块为单位'进行处理
2)各个阶段能够包括'随意多个http模块',并以'流水线(阶段内模块间也有顺序)'的方式处理请求
3)优点:是使处理过程更加'灵活(方便扩展)'、减少'耦合度'
① 了解nginx的11个阶段必要性
1)为后续了解'lua_api'打好基础;因为好多'lua指令'是依托于nginx的'13'个'某一个'阶段
2)运维在'配置' nginx 过程中,出现很多'非预期'的问题,有必要'了解'nginx的'执流程'
理解思路: '指令' --> 所属'模块' --> 所属'阶段(注意同一个阶段不同模块的顺序)'
② 11个阶段示意图
1)除nginx的'filter模块'和'只提供变量的nginx模块'之外
2)所有'其它'nginx模块都'必须'从nginx定义的11个阶段'开始处'进行'请求的处理'
3)一个模块'何时'生效? 有没有'机会(是否跳过)'生效? 要看一个请求处理到'哪个'阶段
1)POST_READ
1)该阶段是 nginx '接收完完整请求头'之后的第一个阶段
2)这个阶段'位于 uri 重写'之前,'没有'做任何加工,因此能'保留'原始信息
3)应用场景:一般用来获取'客户端真实 ip'
4)典型的模块代表: 'realip'
2) SERVER_REWRITE
1)该阶段是 server 级别的 'uri 重写'阶段,该阶段执行处于 'server 块'内,location之'外'
2)该阶段'包含'rewrite 指令、set、if、return 指令
3)典型的模块: 'rewrite'
3) FIND_CONFIG
1)该阶段是'寻找 location 配置'阶段,该阶段使用'重写之后的 uri'来查找对应的 location
细节: 如果匹配到的location 中有'重写指令'的话,该阶段会'再次'执行,直到匹配到'最终'的 location
2)这个阶段的匹配工作是由 'nginx 核心模块'来完成的,并'不支持 其它nginx 模块'注册介入处理
3)find-config 阶段会被'多次执行'的原因
-> 把上阶段的rewrite请求跳转到 find-config 阶段,重新进行请求'uri 和 location'配置块的配对
4)REWRITE
1)该阶段是'location 级别'的'uri 重写'阶段
2)典型模块:'rewrite' -->涉及'set、rewrite、return、if'指令
5)POST_REWRITE
1)该阶段是 location 级别重写的'后一个阶段'
2)常见的两个'用处'
[1]、用来检查上阶段'是否有 uri 重写',并根据结果'跳转到合适'的阶段
1)没有重写,跳转到'下一个'阶段
2)有重写,跳转到'find-config' 阶段
[2]、uri重写的次数是否达到'上限' --> 默认是'10'次 --> 返回'500'报错
3)内部跳转'本质'上其实就是把当前的请求处理阶段'跳回到'find-config 阶段,类似于'条件分支'循环
6)PREACCESS
1)该阶段是'访问权限控制'的'前一'阶段,'预'控制阶段
2)场景:一般也用于限制'速率'、限制'连接数'等
7)ACCESS
1)该阶段是'权限访问控制'阶段
2)场景: 'ip 黑白名单'的权限控制、基于'用户名密码'的权限控制、'第三方'的权限控制
8)POST_ACCESS
1)该阶段是访问控制的'后'一阶段
2)特点:'不支持' 第三方模块处理,由'nginx 核心框架'自己完成处理工作
3)主要是'配合 access 阶段'实现'后续'处理
备注:如果'ACCESS阶段'返回了NGX_HTTP_FORBIDDEN或NGX_HTTP_UNAUTHORIZED,该阶段会'结束'掉请求
3)常用'框架指令'是 satisfy;any 方式,也就是"或"关系、all方式是"且"协作关系
9)PRECONTENT
1)该阶段为生成内容的'前'一阶段
2)主要是用于'处理 try_files 指令(访问静态资源)'的配置
备注: 如果'没有'配置 try_files 指令,这个阶段会'跳过'
10)CONTENT
1)该阶段是所有阶段中'最重要'的一个阶段,该阶段负责'内容生成',并输出 http 响应
2)通过 nginx 配置文件中的配置指令,'生成响应内容',返回给'客户端'
3)涉及模块:echo、proxy 模块
补充: 'filter模块'主要是负责对'content阶段输出的内容'进行再'加工'
11)LOG
1)该阶段就是'日志记录'阶段,根据 'log 配置'写入日志文件
2)该阶段是发送完'响应报文'才记录日志的
思考: 客户端'主动超时'断开导致'header_filter、body_filter'阶段不执行?
③ 源码查看nginx的11个阶段
路径: src/http/ngx_http_core_module.h
补充: nginx的'debug'级别的日志也可以查看'11'个阶段,这里'省略'
④ 11个阶段的处理顺序
1)每个阶段可能有'0个和多个'模块
2)可能存在的'问题':
[1]、如果某个阶段的模块'不再'把请求向'下个'阶段传递,后面的模块是'无法执行'的
典型场景:'return 403','提前'返回给用户
[2]、同一阶段的模块多个模块.并不一定每个模块都会执行到,可能'该阶段前面模块'把请求传递给下一个阶段
典型场景: 'index、autoindex'模块
⑤ 如何看同一阶段内的各模块执行顺序
1)源码执行'configure'后,会在'objs目录'下生成'ngx_modules.c'源文件
2)这个源文件中有两个很重要的全局变量
[1]、ngx_modules -->'前者'保存了nginx将要使用的'全部'模块
[2]、和ngx_module_names -->后者则'记录'了这些'模块的名称'
3)同一阶段内的'各模块'是'倒序'的