1. Nginx处理HTTP请求的11个阶段:
除了 HTTP过滤模块 和 只提供变量的Nginx模块 之外,所有的HTTP模块都必须按照Nginx定义好的11个阶段顺序进行HTTP请求的处理。
所以每一个HTTP模块 何时生效、有没有机会生效,都要看一个请求究竟处理到了哪一个阶段。
2. Nginx是怎样定义这11个处理阶段的:
(1)先来从一个示意图中看 一个请求是怎样在Nginx中被处理的:
一个HTTP请求在Nginx内部的抽象化处理流程:
-
当一个请求进入到图中黄色的框 也就是Nginx之中时,先进行
Read Request Headers
,即读取到请求的头部,并且决定使用哪一个server块的配置去处理这个请求; -
随后进入
Indentify Configuration Block
中寻找哪一个 location 的配置生效了; -
在
Apply Rate Limits
中去决定是否要对其执行 限速(例如连接数太多了超出了限制,或者每秒发送的速率太高了,需要进行限速); -
在
Perform Authentication
中进行权限验证; -
在
Generate Content
中生成HTTP响应,为了生成响应,有时候当Nginx作为反向代理时可能需要跟上游的服务器进行交互,这时就需要进入Upstream Services
中执行,将上游服务器转发给Nginx的内容作为响应内容; -
在向用户返回请求的时候,需要经过
Response Filters
过滤模块,比如通过gzip对还没有压缩的文件进行压缩; -
当发送给用户的时候,还会进入
Log
中记录一条 access日志; -
在上面的流程中有时可能会产生自请求或者重定向,这时就需要进入
Internal redirects and subrequests
这个黄色模块中。
(2)真实的11个处理阶段:
上面示意图中展示的是抽象化的Nginx处理HTTP请求的流程,而实际的执行过程稍微有所区别。
Nginx规定的HTTP请求处理时的11个阶段:
(图中左列表示请求所处的“处理阶段”,右列表示负责这个阶段处理任务的 “HTTP模块”)
所有的HTTP请求都必须是从上到下按照这11个阶段 依次 进行处理!!
而每一个阶段中有可能会有多个模块,那么这些处于同一阶段中的多个模块的处理顺序也很重要,这会在后面的具体章节中介绍。
各个阶段的处理内容:
POST_READ
:在Read到HTTP请求的头部之后的阶段,由 realip模块 负责本阶段的处理,它的作用是在 刚刚读入HTTP头部、没有做任何加工之前,来获取一些原始的数据(例如获取浏览器客户端的IP地址和端口号等);
=============
下面这四个阶段是由HTTP框架来执行,其他第三方模块没有机会在这里执行:
-
SERVER_REWRITE
: 由 rewrite模块 负责处理; -
FIND_CONFIG
:负责做 location{ } 的匹配;
(注:location{} 配置块可以出现在 server配置块和 location配置块 中,即location配置块可以嵌套;
而 server{} 配置块只能出现在 http配置块内,不能嵌套。)
(location 的匹配顺序:“=” 完全匹配;“^~” 匹配上后则不再进行正则表达式匹配;“@” 用于内部跳转。) -
REWRITE
:同样由 rewrite模块 来负责处理; -
POST_WRITE
:在 REWRITE阶段后的阶段,目前没有模块处理这个阶段(包括官方模块);
============
接下来是与ACCESS 相关的三个阶段:(用来确认访问权限)
-
PREACCESS
:在ACCCESS之前的访问权限的确认,主要由 limit_conn模块 和 limit_req 模块负责处理:
limit_conn :判断是否已经达到了最大连接数的限制;(ngx_http_limit_conn_module:限制同一客户端的并发连接数)
limit_req :判断是否已经达到了每秒最大请求数,此时要限制访问速度,并不是客户端就不能访问了;(ngx_http_limit_req_module:把突发的流量限制为恒定的每秒限制多少个请求) -
ACCESS
:用于判断浏览器“能不能访问”它所请求的资源,由以下几个模块负责处理:
access :
根据 用户访问的IP 判断访问权限;(模块:ngx_http_access_module;指令:access – 允许某个address访问、deny – 禁止某个address访问)
auto_basic :
根据 用户名和密码 判断访问权限;(模块:ngx_http_auth_basic_module)
auth_request :
根据一个第三方的服务来判断访问权限(一般是上传到应用服务器上去进行用户名密码验证);(模块:ngx_http_auth_request_module) -
POST_ACCESS
:在ACCESS之后的处理阶段,在第三部分中没有模块会涉及到这一阶段;
============
-
PRECONTENT
:在CONTENT之前的阶段,如 try_files 模块; -
CONTENT
:包括 index模块、autoindex模块、concat模块;
============
LOG
:这一用于打印access日志,由 access_log模块 处理。
3. 这11个处理阶段的执行顺序:
注意事项:
-
在11个阶段中,如果某个阶段的模块处理请求之后,不再把请求向下传递,那么下面阶段的模块是得不到执行的;
-
且同一个阶段的所有模块也并不一定都有机会执行到,可能会有某个模块直接把请求传递给了下一个阶段的模块去处理,那么当前阶段的其他模块就得不到执行了。
这11阶段中的不同模块间的执行的顺序如下:
灰色部分的三个阶段的模块是由HTTP框架进行执行的,其他的第三方模块没有机会在这里执行。
上面图中展示的示意图是指 如果所有的模块全部执行,会是这样的顺序,也有可能不会全部执行,例如执行access模块之后,直接跳转到precontent阶段的 try_files 模块;执行 index模块之后,直接跳转到 log阶段的log模块 等等。