设为首页 收藏本站
查看: 714|回复: 0

[经验分享] Nginx 配置指令的执行顺序(三)同一阶段的执行顺序 & access 阶段 (转载)

[复制链接]

尚未签到

发表于 2016-12-28 10:00:12 | 显示全部楼层 |阅读模式
  转载自 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 之前执行,而无论它们在配置文件中的书写顺序是怎样的。所以,为了避免阅读配置时的混乱,我们应该总是让指令的书写顺序和它们的实际执行顺序保持一致

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-320526-1-1.html 上篇帖子: 使用ab对nginx进行压力测试(ab性能压测用例) 下篇帖子: Nginx 配置指令的执行顺序(六)静态资源服务模块 (转载)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表