关于Nginx处理HTTP请求的11个阶段流程

nginx实际把http请求处理流程划分为了11个阶段,这样划分的缘由是将请求的执行逻辑细分,以模块为单位进行处理,各个阶段能够包含任意多个http模块并以流水线的方式处理请求。这样作的好处是使处理过程更加灵活、下降耦合度。可让每一个HTTP模块能够仅仅专一于完成一个独立,简单的功能。而一个请求的完整处理过程能够由多个HTTP模块共同合做完成。能够极大的提升多个模块合做的协同性,可测试性,可扩展性。换言之,nginx在处理每个http请求,和配置文件上的顺序没有关系。这11个http阶段以下所示:html

1)ngx_http_post_read_phase:nginx

接收到完整的http头部后处理的阶段,它位于uri重写以前,实际上不多有模块会注册在该阶段,默认的状况下,该阶段被跳过。服务器

最早执行的 post-read 阶段在 Nginx 读取并解析完请求头(request headers)以后就当即开始运行。例如:使用了 ngx_realip 模块提供的 set_real_ip_from 和 real_ip_header 这两条配置指令并发

2)ngx_http_server_rewrite_phase:post

uri与location匹配前,修改uri的阶段,用于重定向,也就是该阶段执行处于server块内,location块外的重写指令,在读取请求头的过程当中nginx会根据host及端口找到对应的虚拟主机配置。测试

因为 server-rewrite 阶段位于 post-read 阶段以后,因此 server 配置块中的 set 指令也就老是运行在 ngx_realip 模块改写请求的来源地址以后。lua

3)ngx_http_find_config_phase:url

根据uri寻找匹配的location块配置项阶段,该阶段使用重写以后的uri来查找对应的location,值得注意的是该阶段可能会被执行屡次,由于也可能有location级别的重写指令。日志

这个阶段并不支持 Nginx 模块注册处理程序,而是由 Nginx 核心来完成当前请求与 location 配置块之间的配对工做。换句话说,在此阶段以前,请求并无与任何 location 配置块相关联。所以,对于运行在 find-config 阶段以前的 post-read 和 server-rewrite 阶段来讲,只有 server 配置块以及更外层做用域中的配置指令才会起做用。这就是为何只有写在 server 配置块中的 ngx_rewrite 模块的指令才会运行在 server-rewrite 阶段,这也是为何前面全部例子中的 ngx_realip 模块的指令也都特地写在了 server 配置块中,以确保其注册在 post-read 阶段的处理程序可以生效。server

4)ngx_http_rewrite_phase:

上一阶段找到location块后再修改uri,location级别的uri重写阶段,该阶段执行location基本的重写指令,也可能会被执行屡次。

因为 Nginx 已经在 find-config 阶段完成了当前请求与 location 的配对,因此从 rewrite 阶段开始,location 配置块中的指令即可以产生做用。当 ngx_rewrite 模块的指令用于 location 块中时,即是运行在这个 rewrite 阶段。

5)ngx_http_post_rewrite_phase:

防止重写url后致使的死循环,location级别重写的后一阶段,用来检查上阶段是否有uri重写,并根据结果跳转到合适的阶段。

这个阶段也像 find-config 阶段那样不接受 Nginx 模块注册处理程序,而是由 Nginx 核心完成 rewrite 阶段所要求的“内部跳转”操做(若是 rewrite 阶段有此要求的话)。例如:经过 rewrite 指令把当前请求的 URI 无条件地改写为 /bar,同时发起一个“内部跳转”,最终跳进了 location /bar 中。这里比较有趣的地方是“内部跳转”的工做原理。“内部跳转”本质上其实就是把当前的请求处理阶段强行倒退到 find-config 阶段,以便从新进行请求 URI 与 location 配置块的配对。

6)ngx_http_preaccess_phase:

下一阶段以前的准备,访问权限控制的前一阶段,该阶段在权限控制阶段以前,通常也用于访问控制,好比限制访问频率,连接数等。

该阶段在 access 阶段以前执行,故名 preaccess.标准模块 ngx_limit_req 和 ngx_limit_zone 就运行在此阶段,前者能够控制请求的访问频度,然后者能够限制访问的并发度。

7)ngx_http_access_phase:

让http模块判断是否容许这个请求进入nginx服务器,访问权限控制阶段,好比基于ip黑白名单的权限控制,基于用户名密码的权限控制等。

标准模块 ngx_access、第三方模块 ngx_auth_request 以及第三方模块 ngx_lua 的 access_by_lua 指令就运行在这个阶段。

8)ngx_http_post_access_phase:

访问权限控制的后一阶段,该阶段根据权限控制阶段的执行结果进行相应处理,向用户发送拒绝服务的错误码,用来响应上一阶段的拒绝。

这个阶段也和 post-rewrite 阶段相似,并不支持 Nginx 模块注册处理程序,而是由 Nginx 核心本身完成一些处理工做。post-access 阶段主要用于配合 access 阶段实现标准 ngx_http_core 模块提供的配置指令 satisfy 的功能。对于多个 Nginx 模块注册在 access 阶段的处理程序, satisfy 配置指令能够用于控制它们彼此之间的协做方式。好比模块 A 和 B 都在 access 阶段注册了与访问控制相关的处理程序,那就有两种协做方式,一是模块 A 和模块 B 都得经过验证才算经过,二是模块 A 和模块 B 只要其中任一个经过验证就算经过。第一种协做方式称为 all 方式(或者说“与关系”),第二种方式则被称为 any 方式(或者说“或关系”)。默认状况下,Nginx 使用的是 all 方式。

9)ngx_http_try_files_phase:

为访问静态文件资源而设置,try_files指令的处理阶段,若是没有配置try_files指令,则该阶段被跳过。

这个阶段专门用于实现标准配置指令 try_files 的功能,并不支持 Nginx 模块注册处理程序。try_files 指令接受两个以上任意数量的参数,每一个参数都指定了一个 URI. 这里假设配置了 N 个参数,则 Nginx 会在 try-files 阶段,依次把前 N-1 个参数映射为文件系统上的对象(文件或者目录),而后检查这些对象是否存在。一旦 Nginx 发现某个文件系统对象存在,就会在 try-files 阶段把当前请求的 URI 改写为该对象所对应的参数 URI(但不会包含末尾的斜杠字符,也不会发生 “内部跳转”)。若是前 N-1 个参数所对应的文件系统对象都不存在,try-files 阶段就会当即发起“内部跳转”到最后一个参数(即第 N 个参数)所指定的 URI.经过 root 配置指令所指定的“文档根目录”进行映射。例如,当“文档根目录”是 /var/www/ 的时候,请求 URI /foo/bar 会被映射为文件 /var/www/foo/bar,而请求 URI /foo/baz/ 则会被映射为目录 /var/www/foo/baz/. 注意这里是如何经过 URI 末尾的斜杠字符是否存在来区分“目录”和“文件”的。

10)ngx_http_content_phase:

处理http请求内容的阶段,大部分http模块介入这个阶段,内容生成阶段,该阶段产生响应,并发送到客户端。

Nginx 的 content 阶段是全部请求处理阶段中最为重要的一个,由于运行在这个阶段的配置指令通常都肩负着生成“内容”(content)并输出 HTTP 响应的使命。正由于其重要性,这个阶段的配置指令也异常丰富。如echo、 echo_exec 指令, proxy_pass 指令, echo_location 指令,content_by_lua

11)ngx_http_log_phase:

log阶段处理,好比记录访问量/统计平均响应时间。log_by_lua

处理完请求后的日志记录阶段,该阶段记录访问日志。

以上11个阶段中,http没法介入的阶段有4个:

3)ngx_http_find_config_phase

5)ngx_http_post_rewrite_phase

8)ngx_http_post_access_phase

9)ngx_http_try_files_phase

剩余的7个阶段,http模块均能介入,每一个阶段可介入模块的个数也是没有限制的,多个http模块可同时介入同一阶段并做用于同一请求。

 

 

参考博客:http://www.javashuo.com/article/p-rlxnmqyc-o.html

http://www.javashuo.com/article/p-kelljnak-cw.html

相关文章
相关标签/搜索