Nginx执行阶段

Nginx 介绍
Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强
OpenResty介绍
OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关

执行阶段前言 location /test { set $a 32; echo $a; set $a 56; echo $a; }

两次都会输出56,因为set阶段始终在content阶段之前执行,跟代码的先后顺序无关。

Nginx执行阶段

Nginx 处理请求的过程一共划分为 11 个阶段,按照执行顺序依次是 post-read、server-rewrite、find-config、rewrite、post-rewrite、preaccess、access、post-access、try-files、content 以及 log

post-read 阶段

该阶段Nginx标准函数 set_real_ip_from、real_ip_header
最先执行的 post-read 阶段在 Nginx 读取并解析完请求头(request headers)之后就立即开始运行。标准模块 ngx_realip 就在 post-read 阶段注册了处理程序,它的功能是迫使 Nginx 认为当前请求的来源地址是指定的某一个请求头的值。下面这个例子就使用了 ngx_realip 模块提供的 set_real_ip_from 和 real_ip_header

server { listen 8080; set_real_ip_from 127.0.0.1; real_ip_header X-My-IP; location /test { set $addr $remote_addr; echo "from: $addr"; } }

这里的配置是让 Nginx 把那些来自 127.0.0.1 的所有请求的来源地址,都改写为请求头 X-My-IP 所指定的值。同时该例使用了标准内建变量 $remote_addr 来输出当前请求的来源地址,以确认是否被成功改写。

$ curl -H 'X-My-IP: 1.2.3.4' localhost:8080/test from: 1.2.3.4 server-rewrite阶段

该阶段包含标准函数ngx_rewrite、set 以及openresty函数set_by_lua、rewrite_by_lua
post-read 阶段之后便是 server-rewrite 阶段。当 ngx_rewrite 模块的配置指令直接书写在 server 配置块中时,基本上都是运行在 server-rewrite 阶段。

server { listen 8080; location /test { set $b "$a, world"; echo $b; } set $a hello; }

这里,配置语句 set $a hello 直接写在了 server 配置块中,因此它就运行在 server-rewrite 阶段。而 server-rewrite 阶段要早于 rewrite 阶段运行,因此写在 location 配置块中的语句 set $b "$a, world" 便晚于外面的 set $a hello 语句运行。该例的测试结果证明了这一点:

$ curl localhost:8080/test hello, world find-config 阶段

这个阶段并不支持 Nginx 模块注册处理程序,而是由 Nginx 核心来完成当前请求与 location 配置块之间的配对工作。

location /hello { echo "hello world"; } rewrite 阶段

该阶段包含标准函数set_unescape_uri、rewrite以及openresty函数set_by_lua、 rewrite_by_lua

post-rewrite 阶段

post-rewrite 阶段,不接受 Nginx 模块注册处理程序,而是由 Nginx 核心完成 rewrite 阶段所要求的“内部跳转”操作
“内部跳转”的工作原理:本质上其实就是把当前的请求处理阶段强行倒退到 find-config 阶段,以便重新进行请求 URI 与 location 配置块的配对。比如例中,运行在 rewrite 阶段的 rewrite 指令就让当前请求的处理阶段倒退回了 find-config 阶段。由于此时当前请求的 URI 已经被 rewrite 指令修改为了 /bar,所以这一次换成了 location /bar 与当前请求相关联,然后再接着从 rewrite 阶段往下执行。
为什么不直接在 rewrite 指令执行时立即进行跳转呢?
为了在最初匹配的 location 块中支持多次反复地改写 URI

server { listen 8080; location /foo { set $a hello; rewrite ^ /bar; } location /bar { echo "a = [$a]"; } } location /foo { rewrite ^ /bar; rewrite ^ /baz; echo foo; } location /bar { echo bar; } location /baz { echo baz; }

注意的:如果在 server 配置块中直接使用 rewrite 配置指令对请求 URI 进行改写,则不会涉及“内部跳转”

server { listen 8080; rewrite ^/foo /bar; location /foo { echo foo; } location /bar { echo bar; } } preaccess 阶段

该阶段包含标准函数ngx_access-allow deny ngx_limit_req 和 ngx_limit_zone ngx_auth_request 以及openresty函数access_by_lua其中也包含了限频限流模块resty.limit.req resty.limit.conn
注意的是:标准模块 ngx_realip 其实也在这个阶段注册了处理程序

server { listen 8080; location /test { set_real_ip_from 127.0.0.1; real_ip_header X-Real-IP; echo "from: $remote_addr"; } }

与先看前到的例子相比,此例最重要的区别在于把 ngx_realip 的配置指令放在了 location 配置块中。前面我们介绍过,Nginx 匹配 location 的动作发生在 find-config 阶段,而 find-config 阶段远远晚于 post-read 阶段执行,所以在 post-read 阶段,当前请求还没有和任何 location 相关联。
建议是:尽量在 server 配置块中配置 ngx_realip 这样的模块

post-access阶段

该阶段不支持 Nginx 模块注册处理程序,而是由 Nginx 核心自己完成一些处理工作

try-files 阶段

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/4c70bd71a3b2b805f7f666a3a46bac2f.html