01
介绍
Nginx的map命令主要功能为:根据入参值匹配特定的结果去赋值另外一个新的变量,其匹配的结果可以是一个固定值,也可是一个变量。与geo命令类似,但geo命令的入参值只能是ip格式的值,而map可以根据任何类型的入参。02
安装
Map命令的由ngx_http_map_module模块实现,默认安装已包含此模块,可直接使用。除非在编译安装的时候排除了此模块(--without-http_map_module)03
模块介绍
ngx_http_map_module模块共包含3指令:map、map_hash_bucket_size、map_hash_max_size,其中map_hash_bucket_size、map_hash_max_size这2个指令不用单独显式配置,使用默认配置即可。Syntax: map_hash_bucket_size size;
Default: map_hash_bucket_size 32|64|128;
Context: http
此指令用于设置map变量hash表的桶空间大小,默认值为处理器的缓存行大小。此指令只可在http上下文配置。(默认不配即可) (具体hash表存储原理参考: https://blog.csdn.net/u012062760/article/details/48140449 )
Syntax: map_hash_max_size size;
Default: map_hash_max_size 2048;
Context: http
此指令用于设置map变量 hash表的最大值。
Syntax: map string $variable { ... }
Default: —
Context: http
Map指令是模块最常用指令:将第一个参数值(string)根据匹配结果赋值给第二个变量($variable)。 官方样例如下:
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;
}
Map指令的 第一个参数(string) 可以是一个数据源或者多个数据源的聚合,例如可以是单独的$http_host入参,也可以是$http_host$http_user_agent拼接聚合入参。 变量名($variable) 是我们在业务逻辑中使用的变量名称。 最后的 大括号结构体 存储映射关系,映射的规则可以为字符串或者正则表达式,映射的结果为字符串。默认情况匹配是忽略大小写的,如果需要区分大小写可使用正则匹配,区分大小写的正则匹配,需要以“〜”符号开头,不需要区分大小写的正则匹配需要以“〜*”开头。对于一些需要转移的字符,需在其前面加“\”转义符。 特殊参数 : Map的映射除了正常的映射关系,还包含以下特殊参数: default :设置默认值,如果没有一条映射匹配,将取default值对$variable变量赋值,如果未指定default,则默认值为空字符串。 hostnames :允许使用前缀或者后缀掩码指定域名作为源变量值。这个参数必须写在映射列表的最前面,例如上面的官方示例。 include :包含映射关系的配置文件。如果有大量的映射配置,可以抽取单独的文件保存,方便管理 volatile :表示该变量不缓存 (具体参考: https://stackoverflow.com/questions/46247087/how-to-make-map-derived-variable-reflect-the-current-uri ) 匹配规则: 如果源值匹配多个规则,无论是掩码匹配还是正则匹配,都将按照以下优先级顺序匹配并取用第一个匹配的值。
不带掩码的字符串值
带有前缀掩码的最长字符串值,例如 “ * .example.com”
带后缀掩码的最长字符串值,例如 “mail.*”
第一个匹配的正则表达式(按在配置文件中出现的顺序)
默认值
04
样例
#样例1 根据source入参设置每个渠道 限流速度map $arg_source $limit { default 1; "channel1" 100; "channel2" 200;}#样例2:根据浏览器标识将其匹配的结果写入到$agent变量map $http_user_agent $agent { default ""; ~curl curl; ~*apachebench" ab;}#样例3:根据请求判断uri是否以‘.php’结尾的请求map $uri $isphp { ~\.php$ 1; default 0;}#样例4:获取请求uri的后缀名称map $uri $fileext { ~*.+\.(.+)$ $1; default '';}#样例5:获取请求uri的后缀名称(给匹配的结果集复制到一个特定变量)map $uri $fileext2 { ~*.+\.(?.+)$ $ext; default '';}#样例6:根据浏览器标识验证是移动端访问还是pc端访问map $http_user_agent $device { default 'null'; ~(iPhone|Android) "mobile"; ~(MSIE|Mozilla) "PC";}server { listen 8000; default_type text/plain; location / { echo $limit; echo $agent; echo $isphp; echo $fileext; echo $fileext2; echo $device; }}
执行结果如下:$ curl 127.0.0.1:8000/hello.php?source=channel1100curl1phpphpnull$ curl 127.0.0.1:8000/hello.php1curl1phpphpnull$ curl 127.0.0.1:80001curl0null
注:样例只为介绍使用技巧05
写在最后
同geo一样,由于仅仅在调用此变量的时候才对其进行求值,所以在http上下文中声明大量的map变量也不会增加请求的额外成本。 官方文档:http://nginx.org/en/docs/http/ngx_http_map_module.html
写作不易,如果你看到了最后,能从文章中获取新的知识、或者能巩固你的知识,请关注下公众号,也是对作者创作的鞭策