网站首页 > 精选教程 正文
在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-09-24 CentOS环境下Nginx实现3台虚拟机负载均衡
- 2024-09-24 JVM调优不知道怎么回答,阿里总结四大模块,学不会就背过来
- 2024-09-24 Tomcat、JVM 参数如何调到性能最好?
- 2024-09-24 Nginx在高并发下的性能优化点!有这篇就够了!
- 2024-09-24 Tomcat 和 JVM 的性能调优总结
- 2024-09-24 tomcat 性能调优
- 2024-09-24 Java Web应用调优线程池:没你想的那么复杂
- 2024-09-24 还在不停压榨Tomcat?一份文档带你学习上百种调优方式
- 2024-09-24 《Tomcat和JVM 的性能调优经验总结》
- 2024-09-24 2020最新调优、微服务、框架、分布式指南,我的“大厂”不是梦
你 发表评论:
欢迎- 最近发表
-
- java 服务之间调用(rpc)(java实现服务器)
- Java机器学习库(Java ML)(二、聚类)
- 「Java库」如何使用优秀的加密库Jasypt来保护你的敏感信息?
- GitHub精选 | 轻量级Android和Java日志库
- Java面试官:MySQL binlog 有什么作用?主从延迟的了解么?
- Excel函数核武器库:50个高频场景公式——第二弹
- Excel函数核武器库:50个高频场景公式——第一弹
- Spring Cache高性能缓存库 - Caffeine简介
- Java通过Kafka Streams库来实现数据流处理
- 一连问了好几个大佬,竟然都不知道Redis为什么默认16个数据库?
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)