https://www.diewufeiyang.com/post/578.html

在设置了“取处理程序”的情况下,Nginx 变量也可以选择将其值容器用作缓存,这样在多次读取变量的时候,就只需要调用“取处理程序”计算一次。我们下面就来看一个这样的例子:

Bash
    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 指令定义的映射规则:

Bash
    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 原先的值是怎样的。然而测试结果并非如此:

Bash
    $ 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:

Bash
    $ 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 语句:

Bash
    set $b "$a,$a";

这里会在执行 set 规定的赋值操作时,“主动”地计算出变量 $b 的值,而不会将该求值计算延缓到变量 $b 实际被读取的时候。

【转帖】nginx变量使用方法详解-4的更多相关文章

  1. [转帖]Nginx rewrite模块深入浅出详解

    Nginx rewrite模块深入浅出详解 https://www.cnblogs.com/beyang/p/7832460.html rewrite模块(ngx_http_rewrite_modul ...

  2. [转帖]Nginx安装及配置详解 From https://www.cnblogs.com/zhouxinfei/p/7862285.html

    Nginx安装及配置详解   nginx概述 nginx是一款自由的.开源的.高性能的HTTP服务器和反向代理服务器:同时也是一个IMAP.POP3.SMTP代理服务器:nginx可以作为一个HTTP ...

  3. [转帖]nginx服务器安装及配置文件详解

    nginx服务器安装及配置文件详解 http://seanlook.com/2015/05/17/nginx-install-and-config/  发表于 2015-05-17 |  更新于: 2 ...

  4. [转帖]Vim编辑器使用方法详解

    Vim编辑器使用方法详解 程序员小新人学习 2018-12-16 12:26:23 转载于https://www.cnblogs.com/libaoliang/articles/6961676.htm ...

  5. Linux设置和查看环境变量的方法 详解

    1. 显示环境变量HOME $ echo $HOME /home/redbooks 2. 设置一个新的环境变量hello $ export HELLO="Hello!" $ ech ...

  6. Pythony的数据类型和变量使用方法详解

    数据类型:计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等各种各样的数据,不同的数据,需要定 ...

  7. Nginx服务器中配置非80端口的端口转发方法详解

    这篇文章主要介绍了Nginx服务器中配置非80端口的端口转发方法详解,文中使用到了Nginx中的proxy_pass配置项,需要的朋友可以参考下 nginx可以很方便的配置成反向代理服务器: 1 2 ...

  8. 2-4、nginx特性及基础概念-nginx web服务配置详解

    Nginx Nginx:engine X 调用了libevent:高性能的网络库 epoll():基于事件驱动event的网络库文件 Nginx的特性: 模块化设计.较好扩展性(不支持模块动态装卸载, ...

  9. 【第六课】Nginx常用配置下详解

    目录 Nginx常用配置下详解 1.Nginx虚拟主机 2.部署wordpress开源博客 3.部署discuz开源论坛 4.域名重定向 5.Nginx用户认证 6.Nginx访问日志配置 7.Ngi ...

  10. session的使用方法详解

    session的使用方法详解 Session是什么呢?简单来说就是服务器给客户端的一个编号.当一台WWW服务器运行时,可能有若干个用户浏览正在运正在这台服务器上的网站.当每个用户首次与这台WWW服务器 ...

随机推荐

  1. POJ 1156 单调队列优化

    原题链接 题意 给我们一个n * m矩阵,要求我们求出一个面积最大的子矩阵,满足其内部的极差小于等于c, 同时宽度小于等于100 输入 m, n, c,求这个最大面积.n,m <= 700,c ...

  2. Cesium渲染一帧中用到的图形技术

    译者注:本文翻译自Cesium官方博文<Graphics Tech in Cesium - Rendering a Frame>,May 14, 2015 by Patrick Cozzi ...

  3. 10个安全问题带你了解OWASP 定义的大模型应用

    摘要:OWASP 的一群研究人员,总结目前大模型中可能存在的TOP10安全风险,很好的揭示了我们在大模型应用中需要防护的目标,以及如何采取相应的防护措施. 本文分享自华为云社区<OWASP 定义 ...

  4. 5大特性,带你认识化繁为简的华为云CodeArts Deploy

    摘要:2月27日,华为云发布持续部署服务CodeArts Deploy,通过模块化自由编排部署流程,实现软件的自动化部署,帮助企业软件产品的快速.高效.高质量交付. 本文分享自华为云社区<化繁为 ...

  5. 万物皆可Cassandra:HUAWEI Tag背后的神仙数据库

    摘要:在GaussDB(for Cassandra)的支撑下,HUAWEI Tag防丢精灵表现出了非常强大的核心竞争力. 本文分享自华为云社区<万物皆可Cassandra--HUAWEI Tag ...

  6. 华为海外女科学家为您揭秘:GaussDB(for MySQL)云栈垂直集成的力量有多大?

    摘要:让数据库性能UP!UP!UP!华为云GaussDB(for MySQL)是这样做的 本文分享自华为云社区<华为海外女科学家为您揭秘:GaussDB(for MySQL)云栈垂直集成的力量有 ...

  7. 还在用 Excel 和 SQL?火山引擎 VeDI 这款产品帮你更快处理数据

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,并进入官方交流群 对大多数职场打工人来说,看数据.用数据一直是项有"门槛"的工作. 特别是在企业业务快速发展的背景下,为 ...

  8. python中的代码运行时间获取方式

    python中的代码运行时间获取方式 ​ 我们知道为了提高代码的运行速度,我们需要对书写的python代码进行性能测试,而代码性能的高低的直接反馈就是电脑运行代码所需要的时间. 使用time模块对代码 ...

  9. esp8266 水墨屏显示中文之简单字库

    esp8266 驱动水墨屏显示中文,假设在此之前已经安装好arduino,配置好esp8266的开发环境.水墨屏显示中文的步骤如下: 一.下载库 安装esp8266需要的库文件: GxEPD2 屏幕驱 ...

  10. 拥抱智能,AI 视频编码技术的新探索

    随着视频与交互在日常生活中的作用日益突显,愈发多样的视频场景与不断提高的视觉追求对视频编码提出更高的挑战.相较于人们手工设计的多种视频编码技术,AI 编码可以从大数据中自我学习到更广泛的信号内在编码规 ...