`
风过无声
  • 浏览: 92612 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Nginx 配置指令的执行顺序(三)同一阶段的执行顺序 & access 阶段 (转载)

 
阅读更多

转载自 http://blog.sina.com.cn/openresty

 

如前文所述,除非像 ngx_set_misc 模块那样使用特殊技术,其他模块的配置指令即使是在 rewrite 阶段运行,也不能和 ngx_rewrite 模块的指令混合使用。不妨来看几个这样的例子。

 

    第三方模块 ngx_headers_more 提供了一系列配置指令,用于操纵当前请求的请求头和响应头。其中有一条名叫 more_set_input_headers 的指令可以在 rewrite 阶段改写指定的请求头(或者在请求头不存在时自动创建)。这条指令总是运行在 rewrite 阶段的末尾,该指令的文档中有这么一行标记:

    phase: rewrite tail

其中的 rewrite tail 的意思就是 rewrite 阶段的末尾。

 

    既然运行在 rewrite 阶段的末尾,那么也就总是会运行在 ngx_rewrite 模块的指令之后,即使我们在配置文件中把它写在前面,例如:

    ? location /test {

    ?     set $value dog;

    ?     more_set_input_headers "X-Species: $value";

    ?     set $value cat;

    ?

    ?     echo "X-Species: $http_x_species";

    ? }

这个例子用到的 $http_XXX 内建变量在读取时会返回当前请求中名为 XXX 的请求头,我们在 Nginx 变量漫谈(二) 中曾经简单提过它。需要注意的是,$http_XXX 变量在匹配请求头时会自动对请求头的名字进行归一化,即将名字的大写字母转换为小写字母,同时把间隔符(-)替换为下划线(_),所以变量名 $http_x_species 才得以成功匹配 more_set_input_headers 语句中设置的请求头 X-Species.

 

    此例书写的指令顺序会误导我们认为 /test 接口输出的 X-Species 头的值是 dog,然而实际的结果却并非如此:

    $ curl 'http://localhost:8080/test'

    X-Species: cat

显然,写在 more_set_input_headers 指令之后的 set $value cat 语句却先执行了。

 

    上面这个例子证明了即使运行在同一个请求处理阶段,分属不同模块的配置指令也可能会分开独立运行(除非像 ngx_set_misc 等模块那样针对 ngx_rewrite 模块提供特殊支持)。换句话说,在单个请求处理阶段内部,一般也会以 Nginx 模块为单位进一步地划分出内部子阶段。

 

    第三方模块 ngx_lua 提供的 rewrite_by_lua 配置指令也和 more_set_input_headers 一样运行在 rewrite 阶段的末尾。我们来验证一下:

    ? location /test {

    ?     set $a 1;

    ?     rewrite_by_lua "ngx.var.a = ngx.var.a + 1";

    ?     set $a 56;

    ?

    ?     echo $a;

    ? }

这里我们在 rewrite_by_lua 语句内联的 Lua 代码中对 Nginx 变量 $a 进行了自增计算。从该例的指令书写顺序上看,我们或许会期望输出是 56,可是因为 rewrite_by_lua 会在所有的 set 语句之后执行,所以结果是 57:

    $ curl 'http://localhost:8080/test'

    57

显然,rewrite_by_lua 指令的行为不同于我们前面在 (二) 中介绍过的 set_by_lua 指令。

 

    有的读者可能要问,既然 more_set_input_headers 和 rewrite_by_lua 指令都运行在 rewrite 阶段的末尾,那么它们之间的先后顺序又是怎样的呢?答案是:不一定。我们应当避免写出依赖它们二者间顺序的配置。

 

    Nginx 的 rewrite 阶段是一个比较早的请求处理阶段,这个阶段的配置指令一般用来对当前请求进行各种修改(比如对 URI 和 URL 参数进行改写),或者创建并初始化一系列后续处理阶段可能需要的 Nginx 变量。当然,也不能阻止一些用户在 rewrite 阶段做一系列更复杂的事情,比如读取请求体,或者访问数据库等远方服务,毕竟有 rewrite_by_lua 这样的指令可以嵌入任意复杂的 Lua 代码。

 

    在 rewrite 阶段之后,有一个名叫 access 的请求处理阶段。Nginx 变量漫谈(五) 中介绍过的第三方模块 ngx_auth_request 的指令就运行在 access 阶段。在 access 阶段运行的配置指令多是执行访问控制性质的任务,比如检查用户的访问权限,检查用户的来源 IP 地址是否合法,诸如此类。

 

    例如,标准模块 ngx_access 提供的 allow 和 deny 配置指令可用于控制哪些 IP 地址可以访问,哪些不可以:

    location /hello {

        allow 127.0.0.1;

        deny all;

 

        echo "hello world";

    }

这个 /test 接口被配置为只允许从本机(IP 地址为保留的 127.0.0.1)访问,而从其他 IP 地址访问都会被拒(返回 403 错误页)。ngx_access 模块自己的多条配置指令之间是按顺序执行的,直到遇到第一条满足条件的指令就不再执行后续的 allow 和 deny 指令。如果首先匹配的指令是 allow,则会继续执行后续其他模块的指令或者跳到后续的处理阶段;而如果首先满足的是 deny 则会立即中止当前整个请求的处理,并立即返回 403 错误页。所以看上面这个例子,如果是从本地访问的,则首先匹配 allow 127.0.0.1 这一条语句,于是 Nginx 就继续往下执行其他模块的指令以及后续的处理阶段;而如果是从其他机器访问,则首先匹配的则是 deny all 这一条语句,即拒绝所有地址,它会导致 403 错误页立即返回给客户端。

 

    我们来实测一下。从本机访问这个接口可以得到

    $ curl 'http://localhost:8080/hello'

    hello world

而从另一台机器访问这台机器(假设运行 Nginx 的机器地址是 192.168.1.101)提供的接口时则得到

    $ curl 'http://192.168.1.101:8080/hello'

    <html>

    <head><title>403 Forbidden</title></head>

    <body bgcolor="white">

    <center><h1>403 Forbidden</h1></center>

    <hr><center>nginx</center>

    </body>

    </html>

值得一提的是,ngx_access 模块还支持所谓的“CIDR 记法”来表示一个网段,例如 169.200.179.4/24 则表示路由前缀是 169.200.179.0(或者说子网掩码是 255.255.255.0)的网段。

 

    因为 ngx_access 模块的指令运行在 access 阶段,而 access 阶段又处于 rewrite 阶段之后,所以前面我们见到的所有那些在 rewrite 阶段运行的配置指令,都总是在 allow 和 deny 之前执行,而无论它们在配置文件中的书写顺序是怎样的。所以,为了避免阅读配置时的混乱,我们应该总是让指令的书写顺序和它们的实际执行顺序保持一致

分享到:
评论

相关推荐

    nginx的各项详细配置-超多注释

    - **try_files**: 按顺序查找文件,找到即返回,未找到则按顺序执行下一条指令。 ### 3. Nginx反向代理 通过`proxy_pass`指令,Nginx可以作为反向代理服务器转发请求到后端应用服务器,实现负载均衡、缓存等功能。...

    nginx 配置指南

    **Nginx 配置指南** Nginx 是一款高性能的 Web 服务器和反向代理服务器,被广泛用于处理静态内容、动态内容分发以及负载均衡。本指南将深入探讨 Nginx 的负载均衡实现原理及其配置方法。 **一、Nginx 负载均衡原理...

    NGINX实现一个域名访问多个项目1

    标题中的"NGINX实现一个域名访问多个项目1"是指利用Nginx服务器的配置能力,让同一个域名能够根据不同的URL路径指向不同的应用或项目。描述中提到,这是为了解决在一个域名下部署多个项目的问题,避免为每个项目单独...

    nginx配置参考

    本文将深入探讨Nginx的核心配置概念及其常用指令。 ### 一、Nginx配置文件结构 Nginx的配置文件通常命名为`nginx.conf`,位于安装目录的`conf`子目录下。该文件由一系列块组成,包括全局块、events块、http块、...

    nginx详细配置

    配置Nginx负载均衡通常在http或server块中使用`upstream`指令,然后在location块中通过`proxy_pass`指向upstream。 ```nginx http { upstream backend { server backend1.example.com weight=3; server backend2...

    nginx-1.6.2.rar

    若需平滑重启,可以执行 `nginx -s reload`,这会确保当前处理的请求完成后再重新加载配置。 ### 二、Nginx 负载均衡 负载均衡是 Nginx 的一个重要功能,它可以将来自客户端的请求分散到多个后端服务器,以提高...

    Nginx-1.8.0

    1. **配置结构**:Nginx的配置文件通常为`nginx.conf`,采用层次化的配置结构,由主配置文件、多个服务器块和位置块组成。 2. **主要指令**: - `server_name`:指定服务器的域名或IP地址。 - `listen`:设置...

    18道非常牛逼的Nginx面试题!.zip

    使用access_log指令配置日志文件路径,可选参数包括buffered(缓冲模式)和off(关闭日志)。 12. **Nginx的try_files指令作用是什么?** try_files指令按顺序尝试处理多个文件,当找到匹配项时停止查找并返回...

    誉天邹-Nginx网站架构1-5

    ### 三、Nginx配置与优化技巧 #### 3.1 常用配置指令 - **server**: 定义一个虚拟服务器。 - **location**: 匹配URL路径并指定相应的行为。 - **proxy_pass**: 设置代理转发的目标服务器。 - **gzip**: 开启GZIP...

    nginx负载/代理

    2. **Nginx 配置跨域**:通过在Nginx配置文件中添加适当的`add_header`指令,可以允许特定的跨域请求。例如,可以在HTTP或Server块中设置以下规则: ```nginx add_header Access-Control-Allow-Origin *; add_...

    详解Linux系统配置nginx的负载均衡

    1. **轮询(Round Robin)**:这是最基础的策略,Nginx会按照设定的时间顺序依次将请求发送到各个服务器。如果某台服务器出现故障,Nginx会自动将其排除。 2. **权重(Weight)**:允许为每个服务器分配不同的权重...

    【面试资料】-(机构内训资料)Nginx面试题.zip

    2. **Nginx配置文件结构与指令** - 配置文件结构:全局块、events块、http块、server块、location块,各级别指令的优先级。 - 常用指令:listen、server_name、root、index、location、proxy_pass等。 3. **负载...

    Python3爬虫里关于Splash负载均衡配置详解

    这些服务都需处于同一配置且可正常访问的状态。 接着,选择一台具有公网IP的主机安装Nginx,并编辑其配置文件`nginx.conf`。在http上下文中,创建一个名为`splash`的upstream模块,用于定义后端服务器群。可以使用...

    PHP部分面试题

    #### 十一、Nginx 的负载均衡配置 **Nginx 负载均衡配置示例:** ```nginx upstream backend { server 192.168.1.100; server 192.168.1.101; server 192.168.1.102; } server { listen 80; server_name ...

Global site tag (gtag.js) - Google Analytics