网站首页 > 技术教程 正文
在nginx中所有的变量在定义的时候都会被关联上一个get_handler()方法,所有变量在第一次获取值的时候,都是通过这个handler方法获取的,后续再次获取变量值的时候,是否仍然调用该handler方法则取决于该变量是否可以被缓存。
不可缓存的变量在获取值的时候都是实时计算的,比如“$arg_”开头的动态变量,每次获取值的时候都会从查询参数中重新解析对应的值;而可以缓存的变量并不会每次都调用这个handler方法,在它的整个生命周期中,如果这个变量没有被刷新过,那么自始至终只会调用一次。
nginx中用set指令定义的变量都是可以缓存的,但set指令不会改变已有变量的缓存特性(比如内置变量,但动态变量除外),而所有以“arg_”开头的动态变量都是不可缓存的,这两种变量结合在一起的时候会产生一种有意思的现象,来看一个简单的例子:
location/a {
? ?set $a “$arg_name”;
? ?return 200 “$a = $arg_name”;
}
用curl测试一下:
curl http://127.0.0.1/a?name=zhangsan
zhangsan =zhangsan
这个结果看起来并没有超出我们的预期,跟变量是不是可以缓存好像也没啥关系。
下面我们把这个例子稍微改造一下,改成如下形式:
location /a {
? ?set? $a?“$arg_name”;
? ?set? $args “name=lisi”;
? ?return 200 “$a = $arg_name”;
}
再次用curl测一下:
curl http://127.0.0.1/a?name=zhangsan
zhangsan = 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 http://127.0.0.1/a?name=zhangsan
zhangsan =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 http://127.0.0.1/a
/a
curl http://127.0.0./b
/b
可以看到结果跟预期一致。
在同一个请求中nginx的变量是有全局性的,但仅限于当前请求中。不管变量的更改发生在配置文件的哪个位置,在同一个请求中都可以被看到,看下面一个例子:
server {
? ?set $a “server”;
? ?location / {
?? ??????set $a “location”;
???????? if ($uri) {
???????? ???set $a “if”;
???????? }
? ???????return 200 “$a”;
? ?}
}
从上面的例子可以看到,变量“$a”被更改了三次。因为“$uri”总会有值,所以if块中的set指令也会执行。这种情况如果在其它语言中一般是输出字符串“location”的,因为每块作用域都会关联一块内存空间来存放本作用域内的变量值。但是nginx在整个请求过程中只会为某个变量保留一份存储空间,所以变量值也会只保留最后一次修改的值,因此上面的例子一定是输出字符串“if”。
猜你喜欢
- 2024-10-11 备战秋招/面试,Nginx学习笔记。金九银十你准备好了吗?
- 2024-10-11 python小课堂37 - 你并没有真正的理解 if name 的作用
- 2024-10-11 Nginx之强大变量运行的原理(nginx数据量很大怎么处理)
- 2024-09-21 简历上写精通Nginx/OpenResty详解,Nginx的核心原理应该不过分吧
- 2024-09-21 Nginx配置可用参数(nginx 配置参数)
- 2024-09-21 Nginx防盗链配置案例配置详解(nginx防御ddos)
- 2024-09-21 后台服务器老是被勒索多半是没有使用Nginx代理
- 2024-09-21 详解linux多线程——互斥锁、条件变量、读写锁、自旋锁、信号量
你 发表评论:
欢迎- 最近发表
-
- Linux新手必看:几种方法帮你查看CPU核心数量
- linux基础命令之lscpu命令(linux中ls命令的用法)
- Linux lscpu 命令使用详解(linux常用ls命令)
- 如何查询 Linux 中 CPU 的数量?这几个命令要知道!
- 在linux上怎么查看cpu信息(linux如何查看cpu信息)
- 查看 CPU 的命令和磁盘 IO 的命令
- 如何在CentOS7上改变网卡名(centos怎么改网卡名字)
- 网工必备Linux网络管理命令(网工必备linux网络管理命令是什么)
- Linux 网络命令知多少(linux 网络 命令)
- Linux通过命令行连接wifi的方式(linux命令行连接无线网)
- 标签列表
-
- 下划线是什么 (87)
- 精美网站 (58)
- qq登录界面 (90)
- nginx 命令 (82)
- nginx .http (73)
- nginx lua (70)
- nginx 重定向 (68)
- Nginx超时 (65)
- nginx 监控 (57)
- odbc (59)
- rar密码破解工具 (62)
- annotation (71)
- 红黑树 (57)
- 智力题 (62)
- php空间申请 (61)
- 按键精灵 注册码 (69)
- 软件测试报告 (59)
- ntcreatefile (64)
- 闪动文字 (56)
- guid (66)
- abap (63)
- mpeg 2 (65)
- column (63)
- dreamweaver教程 (57)
- excel行列转换 (56)
本文暂时没有评论,来添加一个吧(●'◡'●)