编程技术分享平台

网站首页 > 技术教程 正文

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

xnh888 2024-10-05 02:59:15 技术教程 20 ℃ 0 评论


在上一篇文章「系统架构」Nginx调优之变量的使用(3)中我们介绍了变量的可见性及动态内置变量,下面我们继续接着介绍Nginx中的可变变量和不可变变量

可变变量和不可变变量

大部分编程语言在声明变量时一般会有特定的修饰符来标识变量是否可变,比如,java中的“final”修饰符和C中的“const”修饰符。如果某个变量在声明时加上了这些修饰符,那么它在后续是无法再被修改的,这体现了变量的不可变性。

nginx中的变量也存在可变和不可变之分,但是它并没有显著的修饰符,所以从表面上你根本看不出来该变量是否可变。不过nginx在启动过程中提供了一个自检查机制,当在配置文件中试图修改一个不可变变量时,nginx是不会顺利启动的。通过这种机制可以间接的判断某个变量是否可变,这种机制我们在前面已经体验过好多次,其实也算是nginx的一种自我保护机制,尽早发现错误尽早制止错误。

前面讲自定义变量的时候涉及到了两个指令set和geo,现在我们来看看用set指令定义的变量是否可改变,一个例子如下:

location/a {
? ? set $a“old a”;
? ? set $a “new a”;
? ? return 200 “$a”;
}

用curl测验一下:

curl http://127.0.0.1/a
new a

再看一个geo指令的例子:

http {
? ?geo $a {default “old a”}
? ?geo $a {default “new a”}
? ?location /a {
? ? ?return 200 “$a”;
? ?}
}

用curl测验一下:

curl http://127.0.0.1/a
new a

两个例子都可以成功启动并打印数据,因此,我们判定这两个指令定义的变量可以被改变。

记住上面的这个结论,然后咱们再看一个例子:

location /a {
? ?set $host “I am host”;
? ?return 200 “$host”;
}

nginx启动失败,并且打印了一条错误日志:

nginx: [emerg] the duplicate "host"variable in /path/conf/nginx.conf:49 

看到这种结果你可能开始怀疑刚刚得出的结论似乎又是错误的。查阅nginx文档会发现“$host”这个变量是http核心模块中的一个内置变量,此时,你可能会猜测nginx中的内置变量是不可以改变的。为了验证这个结论我们再找一个内置变量验证一下:

location /a {
? ?set $args “I am querystring”;
? ?return 200 “$args”;
}

例子中的“$args”是一个内置变量,表示请求中的查询参数。当我们试图启动nginx的时候发现完全没有问题,而且用curl也可以正确访问,这时候你可能已经懵了,感觉nginx变量的这些行为毫无章法。

实际上这个问题的答案仅从做实验和文档上是找不到的,只能从代码上一窥究竟,不过我不打算带着读者读代码,这里简单说一下原理:

nginx中每个变量在被定义的时候都会打上一个是否可以被改变的标记,然后把放到一个容器中,当后续有人试图再次定义用一个变量的时候,nginx会首先从这个容器中查找这个变量,如果找到相同的变量则需要判断容器中的变量是否存在可改变的标记,如果有则定义的变量会把容器中的变量覆盖掉,如果没有则返回错误并终止nginx启动。

另一个要注意的是,http模块中的内置变量放入该容器中的时机,内置变量要先于“set”或“geo”指令,如果某个内置变量被打上了不可改变的标记,后续其它指令就无法再定义相同名字的变量了。

目前,nginx的核心http模块中几乎所有内置变量都是不可改变的,只有“$args”和“$limit_rate”这两个内置变量可以被改变。

另外,由于http模块的动态内置变量并不会把自己放入到容器中,所以它看起来是可以被改变的,比如:

location/a {
? ?set $arg_a “I am a”;
? ?return 200 “$arg_a”;
}

用curl验证下:

curl http://127.0.0.1/a?a=b
I am a

可以看到这个包含了一个内置变量的例子可以正常启动,并且输出了数据。所以,关于大部分内置变量不可改变这个结论,似乎需要再加上一条:除动态内置变量外。

实际上是因为动态变量被重新定义后它就不再是动态变量了,它之所以不再是动态变量,那是因为动态变量的“定义”发生在所有内置变量和自定义变量之后。在nginx中,一旦某个变量被认定为自定义或内置变量,后续就不会再被赋予动态变量的特性。

比如,例子中的“$arg_a”,其实已经变成了一个自定义变量,相应的动态变量特征也就不存在了,但其它以“$arg_”开头的变量仍然是动态变量。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表