转载自 http://blog.sina.com.cn/openresty
在设置了“取处理程序”的情况下,Nginx 变量也可以选择将其值容器用作缓存,这样在多次读取变量的时候,就只需要调用“取处理程序”计算一次。我们下面就来看一个这样的例子:
map $args $foo {
default 0;
debug 1;
}
server {
listen 8080;
location /test {
set $orig_foo $foo;
set $args debug;
echo "orginal foo: $orig_foo";
echo "foo: $foo";
}
}
这里首次用到了标准 ngx_map 模块的 map 配置指令,我们有必要在此介绍一下。map 在英文中除了“地图”之外,也有“映射”的意思。比方说,中学数学里讲的“函数”就是一种“映射”。而 Nginx 的这个 map 指令就可以用于定义两个 Nginx 变量之间的映射关系,或者说是函数关系。回到上面这个例子,我们用 map 指令定义了用户变量 $foo 与 $args 内建变量之间的映射关系。特别地,用数学上的函数记法 y = f(x) 来说,我们的 $args 就是“自变量” x,而 $foo 则是“因变量” y,即 $foo 的值是由 $args 的值来决定的,或者按照书写顺序可以说,我们将 $args 变量的值映射到了 $foo 变量上。
现在我们再来看 map 指令定义的映射规则:
map $args $foo {
default 0;
debug 1;
}
花括号中第一行的 default 是一个特殊的匹配条件,即当其他条件都不匹配的时候,这个条件才匹配。当这个默认条件匹配时,就把“因变量” $foo 映射到值 0. 而花括号中第二行的意思是说,如果“自变量” $args 精确匹配了 debug 这个字符串,则把“因变量” $foo 映射到值 1. 将这两行合起来,我们就得到如下完整的映射规则:当 $args 的值等于 debug 的时候,$foo 变量的值就是 1,否则 $foo 的值就为 0.
明白了 map 指令的含义,再来看 location /test. 在那里,我们先把当前 $foo 变量的值保存在另一个用户变量 $orig_foo 中,然后再强行把 $args 的值改写为 debug,最后我们再用 echo 指令分别输出 $orig_foo 和 $foo 的值。
从逻辑上看,似乎当我们强行改写 $args 的值为 debug 之后,根据先前的 map 映射规则,$foo 变量此时的值应当自动调整为字符串 1, 而不论 $foo 原先的值是怎样的。然而测试结果并非如此:
$ curl 'http://localhost:8080/test'
original foo: 0
foo: 0
第一行输出指示 $orig_foo 的值为 0,这正是我们期望的:上面这个请求并没有提供 URL 参数串,于是 $args 最初的取值就是空,再根据我们先前定义的映射规则,$foo 变量在第一次被读取时的值就应当是 0(即匹配默认的那个 default 条件)。
而第二行输出显示,在强行改写 $args 变量的值为字符串 debug 之后,$foo 的条件仍然是 0 ,这显然不符合映射规则,因为当 $args 为 debug 时,$foo 的值应当是 1. 这究竟是为什么呢?
其实原因很简单,那就是 $foo 变量在第一次读取时,根据映射规则计算出的值被缓存住了。刚才我们说过,Nginx 模块可以为其创建的变量选择使用值容器,作为其“取处理程序”计算结果的缓存。显然,ngx_map 模块认为变量间的映射计算足够昂贵,需要自动将因变量的计算结果缓存下来,这样在当前请求的处理过程中如果再次读取这个因变量,Nginx 就可以直接返回缓存住的结果,而不再调用该变量的“取处理程序”再行计算了。
为了进一步验证这一点,我们不妨在请求中直接指定 URL 参数串为 debug:
$ curl 'http://localhost:8080/test?debug'
original foo: 1
foo: 1
我们看到,现在 $orig_foo 的值就成了 1,因为变量 $foo 在第一次被读取时,自变量 $args 的值就是 debug,于是按照映射规则,“取处理程序”计算返回的值便是 1. 而后续再读取 $foo 的值时,就总是得到被缓存住的 1 这个结果,而不论 $args 后来变成什么样了。
map 指令其实是一个比较特殊的例子,因为它可以为用户变量注册“取处理程序”,而且用户可以自己定义这个“取处理程序”的计算规则。当然,此规则在这里被限定为与另一个变量的映射关系。同时,也并非所有使用了“取处理程序”的变量都会缓存结果,例如我们前面在 (三) 中已经看到 $arg_XXX 并不会使用值容器进行缓存。
类似 ngx_map 模块,标准的 ngx_geo 等模块也一样使用了变量值的缓存机制。
在上面的例子中,我们还应当注意到 map 指令是在 server 配置块之外,也就是在最外围的 http 配置块中定义的。很多读者可能会对此感到奇怪,毕竟我们只是在 location /test 中用到了它。这倒不是因为我们不想把 map 语句直接挪到 location 配置块中,而是因为 map 指令只能在 http 块中使用!
很多 Nginx 新手都会担心如此“全局”范围的 map 设置会让访问所有虚拟主机的所有 location 接口的请求都执行一遍变量值的映射计算,然而事实并非如此。前面我们已经了解到 map 配置指令的工作原理是为用户变量注册 “取处理程序”,并且实际的映射计算是在“取处理程序”中完成的,而“取处理程序”只有在该用户变量被实际读取时才会执行(当然,因为缓存的存在,只在请求生命期中的第一次读取中才被执行),所以对于那些根本没有用到相关变量的请求来说,就根本不会执行任何的无用计算。
这种只在实际使用对象时才计算对象值的技术,在计算领域被称为“惰性求值”(lazy evaluation)。提供“惰性求值” 语义的编程语言并不多见,最经典的例子便是 Haskell. 与之相对的便是“主动求值” (eager evaluation)。我们有幸在 Nginx 中也看到了“惰性求值”的例子,但“主动求值”语义其实在 Nginx 里面更为常见,例如下面这行再普通不过的 set 语句:
set $b "$a,$a";
这里会在执行 set 规定的赋值操作时,“主动”地计算出变量 $b 的值,而不会将该求值计算延缓到变量 $b 实际被读取的时候。
相关推荐
nginx可以使用变量简化配置与提高配置的灵活性,所有的变量值都可以通过这种方式引用: $变量名 而nginx中的变量分为两种,自定义变量与内置预定义变量 内置变量 声明 可以在sever,http,location等标签中使用...
nginx内置变量文档, 网上收集出来的
第一步:添加nginx.conf的http级别的缓存配置 第二步:在访问静态文件的location上添加缓存 第三步:在proxy_pass跳转的locatio
章亦春nginx漫谈
nginx内置变量列表,根据 Nginx 源码文件 ngx_http_variables.c 提取了nginx 的内置变量。
nginx反向代理、负载均衡、缓存静态资源、URL重定向、读写分离.zip
本文档介使用nginx的缓存模块配置web缓存的方法,实现服务数据的缓存。
主要介绍了使用Nginx作缓存服务器以及删除其缓存文件的方法,作cache时需要注意一下磁盘的IO瓶颈,需要的朋友可以参考下
强烈推荐 打造高性能nginx缓存服务器
一个NGINX conf 配置文件中的变量大全
提供了小程序https服务在nginx环境下的配置示例,包括https配置和小程序扫二维码打开小程序时需要在nginx服务端放置小程序二维码扫描校验文件的配置
因此 在启用多进程时 不能使用共享内存来做SSL的session缓存 也就是说 要实现SSL 只能使用单进程 从而限制了并发连接数 (造成这种结果的原因 可能是作者对Nginx在Windows平台下的应用不太重视 在共享内存中使用了...
Nginx搭建图片服务器(静态资源缓存服务器).zip
ngx_cache_purge 是 nginx 模块,此模块可以清理 nginx 的 FastCGI、proxy、 SCGI 和 uWSGI 的缓存。配置指令(相同位置语法)fastcgi_cache_purgesyntax: fastcgi_cache_purge on|off|<method> [from all|<ip> [.....
nginx图片缓存服务器配置文档.pdf
nginx配置文件nginx.conf ,主要标记了nginx 的负载配置upstream,静态资源缓存,是否开启压缩
最近碰到一个问题就是nginx转发到另一个nginx使用域名不通报502,通过nginx的日志发现如下 10.220.53.117 – – [18/Feb/2020:10:26:07 +0800] “POST /test/v1/api/f1 HTTP/1.1” 502 173 “-” “okhttp/3.11.0”...
NGINX反向代理缓存[参考].pdf
Nginx在反向代理站点的时候,通常会将一些文件进行缓存,特别是静态文件。缓存的部分存储在文件中,每个缓存文件包括“文件头”+“HTTP返回包头”+“HTTP返回包体”。如果二次请求命中了该缓存文件,则Nginx会直接将...
1,nginx内置变量 nginx 有很多内置变量可以进行简单的过滤。 $arg_name 请求行中的name参数。 $args 请求行中参数字符串。 $cookie_name 名为name的cookie。 与$uri相同。 $http_name 任意请求头的值;变量名的后...