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 阶段
实现标准配置指令 try_files 的功能,并不支持 Nginx 模块注册处理程序。
try_files 指令接受两个以上任意数量的参数,每个参数都指定了一个 URI. 这里假设配置了 N 个参数,则 Nginx 会在 try-files 阶段,依次把前 N-1 个参数映射为文件系统上的对象(文件或者目录),然后检查这些对象是否存在。一旦 Nginx 发现某个文件系统对象存在,就会在 try-files 阶段把当前请求的 URI 改写为该对象所对应的参数 URI(但不会包含末尾的斜杠字符,也不会发生 “内部跳转”)。如果前 N-1 个参数所对应的文件系统对象都不存在,try-files 阶段就会立即发起“内部跳转”到最后一个参数(即第 N 个参数)所指定的 URI.
 
location /test {
    try_files /foo /bar/ /baz;
    echo "uri: $uri";
}
 
location /foo {
    echo foo;
}
 
location /bar/ {
    echo bar;
}
 
location /baz {
    echo baz;
}
我们在 location /test 中使用了 try_files 配置指令,并提供了三个参数,/foo、/bar/ 和 /baz. 根据前面对 try_files 指令的介绍,我们可以知道,它会在 try-files 阶段依次检查前两个参数 /foo 和 /bar/ 所对应的文件系统对象是否存在。
不妨先来做一组实验。假设现在 /var/www/ 路径下是空的,则第一个参数 /foo 映射成的文件 /var/www/foo 是不存在的;同样,对于第二个参数 /bar/ 所映射成的目录 /var/www/bar/ 也是不存在的。于是此时 Nginx 会在 try-files 阶段发起到最后一个参数所指定的 URI(即 /baz)的“内部跳转”。实际的请求结果证实了这一点:
 
 $ curl localhost:8080/test
   baz
接下来再做一组实验:在 /var/www/ 下创建一个名为 foo 的文件,其内容为 hello world(注意你需要有 /var/www/ 目录下的写权限):
 
$ echo 'hello world' > /var/www/foo
然后再请求 /test 接口:
 
 $ curl localhost:8080/test
  uri: /foo
这里发生了什么?我们来看, try_files 指令的第一个参数 /foo 可以映射为文件 /var/www/foo,而 Nginx 在 try-files 阶段发现此文件确实存在,于是立即把当前请求的 URI 改写为这个参数的值,即 /foo,并且不再继续检查后面的参数,而直接运行后面的请求处理阶段。
通过前面这几组实验不难看到, try_files 指令本质上只是有条件地改写当前请求的 URI,而这里说的“条件”其实就是文件系统上的对象是否存在。当“条件”都不满足时,它就会无条件地发起一个指定的“内部跳转”。当然,除了无条件地发起“内部跳转”之外, try_files 指令还支持直接返回指定状态码的 HTTP 错误页,例如:
 
 try_files /foo /bar/ =404;
这行配置是说,当 /foo 和 /bar/ 参数所对应的文件系统对象都不存在时,就直接返回 404 Not Found 错误页。注意这里它是如何使用等号字符前缀来标识 HTTP 状态码的。

dawei

【声明】:九江站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。