介绍
默认情况下,Nginx会加载标准模块ngx_http_map_module(或称ngx_map),除非人为的在configure时添加--without-http_map_module选项。
ngx_http_map_module模块可以创建变量,这些变量的值与另外的变量值相关联。允许分类或者同时映射多个值到多个不同值并储存到一个变量中,map指令用来创建变量,但是仅在变量被读取的时候执行计算映射操作,对于处理没有引用变量的请求时,根本不会执行如何无用的计算,所以这个模块并没有性能上的缺失。
Nginx 的这个map指令就可以用于定义两个 Nginx 变量之间的映射关系,或者说是函数关系。
显然,ngx_map 模块认为变量间的映射计算足够昂贵,需要自动将因变量的计算结果缓存下来,这样在当前请求的处理过程中如果再次读取这个因变量,Nginx 就可以直接返回缓存住的结果,而不再调用该变量的“取处理程序”再行计算了。
类似 ngx_map 模块,标准的 ngx_geo 等模块也一样使用了变量值的缓存机制。map 指令只能在 http 块中使用。
很多 Nginx 新手都会担心如此“全局”范围的 map 设置会让访问所有虚拟主机的所有 location 接口的请求都执行一遍变量值的映射计算,然而事实并非如此。前面我们已经了解到 map 配置指令的工作原理是为用户变量注册 “取处理程序”,并且实际的映射计算是在“取处理程序”中完成的,而“取处理程序”只有在该用户变量被实际读取时才会执行(当然,因为缓存的存在,只在请求生命期中的第一次读取中才被执行),所以对于那些根本没有用到相关变量的请求来说,就根本不会执行任何的无用计算。
这种只在实际使用对象时才计算对象值的技术,在计算领域被称为“惰性求值”(lazy evaluation)。提供“惰性求值” 语义的编程语言并不多见,最经典的例子便是 Haskell. 与之相对的便是“主动求值” (eager evaluation)。我们有幸在 Nginx 中也看到了“惰性求值”的例子,但“主动求值”语义其实在 Nginx 里面更为常见,例如下面这行再普通不过的 set 语句:
set $b "$a,$a";
这里会在执行 set 规定的赋值操作时,“主动”地计算出变量 $b 的值,而不会将该求值计算延缓到变量 $b 实际被读取的时候。
模块指令说明
map
语法: map $var1 $var2 { ... }
默认值: —
配置段: http
map为一个变量设置的映射表。映射表由两列组成,依次是匹配模式和对应的值。
在 map 块里的参数指定了源变量值和结果值的对应关系。
匹配模式可以是一个简单的字符串或者正则表达式,使用正则表达式要用('~')。
一个正则表达式如果以 “~” 开头,表示这个正则表达式对大小写敏感。以 “~*”开头,表示这个正则表达式对大小写不敏感。
不能在map块里面引用命名捕获或位置捕获变量。如~^/ttlsa_com/(.*) /boy/$1; 这样会报错Nginx: [emerg] unknown variable。
如果源变量值包含特殊字符如‘~’,则要以‘\’来转义。
default: 指定如果没有匹配结果将使用的默认值。当没有设置default,将会用一个空的字符串作为默认的结果。
hostnames: 允许用前缀或者后缀掩码指定域名作为源变量值。这个参数必须写在值映射列表的最前面。
include file: 包含一个或多个含有映射值的文件。
volatile:暗示变量不能被缓存。
1. 没有掩码的字符串
2. 最长的带前缀的字符串,例如: “*.example.com”
3. 最长的带后缀的字符串,例如:“mail.*”
4. 按顺序第一个先匹配的正则表达式 (在配置文件中体现的顺序)
5. 默认值
map_hash_bucket_size
语法: map_hash_bucket_size size;
默认值: map_hash_bucket_size 32|64|128;
配置段: http
指定一个映射表中的变量在哈希表中的最大值,这个值取决于处理器的缓存。
map_hash_max_size
语法: map_hash_max_size size;
默认值: map_hash_max_size 2048;
配置段: http
设置映射表对应的哈希表的最大值。
实例一
参考文献
[1].http://www.ttlsa.com/Nginx/using-Nginx-map-method/
[2].http://www.ttlsa.com/Nginx/Nginx-var-4/
默认情况下,Nginx会加载标准模块ngx_http_map_module(或称ngx_map),除非人为的在configure时添加--without-http_map_module选项。
ngx_http_map_module模块可以创建变量,这些变量的值与另外的变量值相关联。允许分类或者同时映射多个值到多个不同值并储存到一个变量中,map指令用来创建变量,但是仅在变量被读取的时候执行计算映射操作,对于处理没有引用变量的请求时,根本不会执行如何无用的计算,所以这个模块并没有性能上的缺失。
Nginx 的这个map指令就可以用于定义两个 Nginx 变量之间的映射关系,或者说是函数关系。
显然,ngx_map 模块认为变量间的映射计算足够昂贵,需要自动将因变量的计算结果缓存下来,这样在当前请求的处理过程中如果再次读取这个因变量,Nginx 就可以直接返回缓存住的结果,而不再调用该变量的“取处理程序”再行计算了。
类似 ngx_map 模块,标准的 ngx_geo 等模块也一样使用了变量值的缓存机制。map 指令只能在 http 块中使用。
很多 Nginx 新手都会担心如此“全局”范围的 map 设置会让访问所有虚拟主机的所有 location 接口的请求都执行一遍变量值的映射计算,然而事实并非如此。前面我们已经了解到 map 配置指令的工作原理是为用户变量注册 “取处理程序”,并且实际的映射计算是在“取处理程序”中完成的,而“取处理程序”只有在该用户变量被实际读取时才会执行(当然,因为缓存的存在,只在请求生命期中的第一次读取中才被执行),所以对于那些根本没有用到相关变量的请求来说,就根本不会执行任何的无用计算。
这种只在实际使用对象时才计算对象值的技术,在计算领域被称为“惰性求值”(lazy evaluation)。提供“惰性求值” 语义的编程语言并不多见,最经典的例子便是 Haskell. 与之相对的便是“主动求值” (eager evaluation)。我们有幸在 Nginx 中也看到了“惰性求值”的例子,但“主动求值”语义其实在 Nginx 里面更为常见,例如下面这行再普通不过的 set 语句:
set $b "$a,$a";
这里会在执行 set 规定的赋值操作时,“主动”地计算出变量 $b 的值,而不会将该求值计算延缓到变量 $b 实际被读取的时候。
模块指令说明
map
语法: map $var1 $var2 { ... }
默认值: —
配置段: http
map为一个变量设置的映射表。映射表由两列组成,依次是匹配模式和对应的值。
在 map 块里的参数指定了源变量值和结果值的对应关系。
匹配模式可以是一个简单的字符串或者正则表达式,使用正则表达式要用('~')。
一个正则表达式如果以 “~” 开头,表示这个正则表达式对大小写敏感。以 “~*”开头,表示这个正则表达式对大小写不敏感。
map $http_user_agent $agent { default ""; ~curl curl; ~*apachebench" ab; }正则表达式里可以包含命名捕获和位置捕获,这些变量可以跟结果变量一起被其它指令使用。
map $uri $value { /ttlsa_com /index.PHP; ~^/ttlsa_com/(?<suffix>.*)$ /boy/; ~/fz(/.*) /index.PHP?; }注意:
不能在map块里面引用命名捕获或位置捕获变量。如~^/ttlsa_com/(.*) /boy/$1; 这样会报错Nginx: [emerg] unknown variable。
如果源变量值包含特殊字符如‘~’,则要以‘\’来转义。
map $http_referer $value { Mozilla 111; \~Mozilla 222; }结果变量可以是一个字符串也可以是另外一个变量。
map $num $limit { 1 $binary_remote_addr; 0 ""; }map指令有三个参数:
default: 指定如果没有匹配结果将使用的默认值。当没有设置default,将会用一个空的字符串作为默认的结果。
hostnames: 允许用前缀或者后缀掩码指定域名作为源变量值。这个参数必须写在值映射列表的最前面。
include file: 包含一个或多个含有映射值的文件。
volatile:暗示变量不能被缓存。
map $http_host $name { hostnames; default 0; example.com 1; *.example.com 1; example.org 2; *.example.org 2; .example.net 3; wap.* 4; } map $http_user_agent $mobile { default 0; "~Opera Mini" 1; }如果匹配到多个特定的变量,如掩码和正则同时匹配,那么会按照下面的顺序进行选择:
1. 没有掩码的字符串
2. 最长的带前缀的字符串,例如: “*.example.com”
3. 最长的带后缀的字符串,例如:“mail.*”
4. 按顺序第一个先匹配的正则表达式 (在配置文件中体现的顺序)
5. 默认值
map_hash_bucket_size
语法: map_hash_bucket_size size;
默认值: map_hash_bucket_size 32|64|128;
配置段: http
指定一个映射表中的变量在哈希表中的最大值,这个值取决于处理器的缓存。
map_hash_max_size
语法: map_hash_max_size size;
默认值: map_hash_max_size 2048;
配置段: http
设置映射表对应的哈希表的最大值。
实例一
http { map $args $foo { default 0; debug 1; } server { listen 8087; server_name localhost; location /test { set $orig_foo $foo; set $args debug; echo "orginal foo: $orig_foo"; echo "foo: $foo"; } } }
curl -v 'http://localhost:8087/test'
实例二
http { map $http_user_agent $agent { ~curl curl; ~*chrome chrome; } server { listen 8085; server_name localhost; location /hello { default_type text/plain; echo http_user_agent: $http_user_agent; echo agent: $agent; } } }
curl -v 127.0.0.1:8085/hello
curl -v 127.0.0.1:8085/hello --user-agent Chrome
实例三
http { map $uri $match { ~^/hello/(.*) http://www.ttlsa.com/; } server { listen 8086; server_name localhost; location /hello { default_type text/plain; echo uri: $uri; echo match: $match; echo capture: $1; echo new: $match$1; } } }curl -v http://127.0.0.1:8086/hello/aaa/bbb
参考文献
[1].http://www.ttlsa.com/Nginx/using-Nginx-map-method/
[2].http://www.ttlsa.com/Nginx/Nginx-var-4/
[3].http://Nginx.org/en/docs/http/ngx_http_map_module.html