龙空技术网

「系统架构」Nginx调优之变量的使用(5)

猿话 220

前言:

目前朋友们对“两台nginx请求隔离”大约比较重视,咱们都需要了解一些“两台nginx请求隔离”的相关文章。那么小编也在网摘上搜集了一些有关“两台nginx请求隔离””的相关知识,希望同学们能喜欢,大家一起来了解一下吧!


在nginx中所有的变量在定义的时候都会被关联上一个get_handler()方法,所有变量在第一次获取值的时候,都是通过这个handler方法获取的,后续再次获取变量值的时候,是否仍然调用该handler方法则取决于该变量是否可以被缓存。

不可缓存的变量在获取值的时候都是实时计算的,比如“$arg_”开头的动态变量,每次获取值的时候都会从查询参数中重新解析对应的值;而可以缓存的变量并不会每次都调用这个handler方法,在它的整个生命周期中,如果这个变量没有被刷新过,那么自始至终只会调用一次。

nginx中用set指令定义的变量都是可以缓存的,但set指令不会改变已有变量的缓存特性(比如内置变量,但动态变量除外),而所有以“arg_”开头的动态变量都是不可缓存的,这两种变量结合在一起的时候会产生一种有意思的现象,来看一个简单的例子:

location/a {   set $a “$arg_name”;   return 200 “$a = $arg_name”;}

用curl测试一下:

curl  =zhangsan

这个结果看起来并没有超出我们的预期,跟变量是不是可以缓存好像也没啥关系。

下面我们把这个例子稍微改造一下,改成如下形式:

location /a {   set  $a “$arg_name”;   set  $args “name=lisi”;   return 200 “$a = $arg_name”;}

再次用curl测一下:

curl  = lisi

这时候我们可以看到,“$a”和“$arg_name”这两个变量虽然都是在表示入参name的值,但是且输出了不同的结果。

这其实就是变量是否可缓存的特性引起的,因为变量“$a”是一个可缓存的变量,当被设置后变量值就被保存下来了;而“$arg_name”是一个不可被缓存的变量,每次获取该值的时候都会调用其对应的handler方法。

我们看到第一次调用的时候查询参数值是“name=zhangsan”,这个值被赋值给了变量“$a”,在第二次获取该变量值之前,我们把查询参数改成了“name=lisi”,当它再次调用对应的handler方法的时候获取到的值就变成了“lisi”。

动态内置变量此时仍然是一个特殊的存在,我们之前说过,动态变量被重新定义后它就不再是动态变量了,所以它也就不再保有不可缓存的特性,看个例子就知道了:

location /a {    set $arg_name “$arg_name”;    set $a “$arg_name”;    set $args “name=lisi”;    return 200 “$a = $arg_name”;}

用跟上面同样的入参访问以下该location:

curl  =zhangsan

可以看到这两个变量的值又一样了。其实原因很简单,用set指令重新定义“$arg_name”后它就不再是动态变量了,它原本的不可缓存特性也就不存在了,所以此时查询参数的更改对他也就不起任何作用。

变量的隔离性

nginx中变量的隔离性类似于其它编程语言中变量的作用域,但它又不像其它语言那样有全局和局部变量之分。nginx中的变量隔离是基于请求的,同一个变量在不同的请求中毫无关系,即A请求不会读到(或改变)B请求中的变量值,B也不会读到(改变)A的,比如下面一个例子:

server {   set $a “$uri”;   location /a {     return 200 “I am $a”;   }   location /b {     return 200 “I am $a”;   }}

我们在server块定义了一个看似是“全局变量”的“$a”,如果它有全局性,那么访问上面的两个location的时候肯定会得到相同的值,但nginx中不是这样的。

在nginx中两个location都可以看到这个变量“$a”,这体现了nginx变量的全局可见性;但两个location看到的变量值确实是不一样的,这体现了隔离性。用curl验证一下结论是否正确:

curl  

可以看到结果跟预期一致。

在同一个请求中nginx的变量是有全局性的,但仅限于当前请求中。不管变量的更改发生在配置文件的哪个位置,在同一个请求中都可以被看到,看下面一个例子:

server {   set $a “server”;   location / {         set $a “location”;         if ($uri) {            set $a “if”;         }         return 200 “$a”;   }}

从上面的例子可以看到,变量“$a”被更改了三次。因为“$uri”总会有值,所以if块中的set指令也会执行。这种情况如果在其它语言中一般是输出字符串“location”的,因为每块作用域都会关联一块内存空间来存放本作用域内的变量值。但是nginx在整个请求过程中只会为某个变量保留一份存储空间,所以变量值也会只保留最后一次修改的值,因此上面的例子一定是输出字符串“if”。

标签: #两台nginx请求隔离