Nginx 的 map 指令是一个非常强大的功能,用于根据输入变量的值创建新的变量。你可以通过 map 指令来定义一个变量,并根据某些条件设置它的值。这通常用于根据客户端请求的某些属性(例如主机名、IP 地址、请求 URI 等)动态选择配置选项,如后端服务器、重定向目标、响应内容等。
基本语法
map $variable_to_map $new_variable {
default value_if_no_match; # 默认值(可选)
condition_1 value_1; # 条件1
condition_2 value_2; # 条件2
…
}
• $variable_to_map:表示要检查的输入变量,比如 $host、$uri、$remote_addr 等。
• $new_variable:表示通过 map 指令定义的新变量,这个变量的值根据条件来设置。
• default:可选的,表示如果没有匹配到任何条件时使用的默认值。
• condition_x:条件,根据输入变量的值进行匹配,可以是精确值或正则表达式。
• value_x:当条件匹配时为新变量赋的值。
示例用法
- 基于域名选择后端
假设你有多个域名,想根据请求的域名($host)来决定请求发送到哪个后端服务器,可以通过 map 指令动态设置 upstream。
http {
upstream backend1 {
server 192.168.1.1;
}
upstream backend2 {server 192.168.1.2;
}# 基于主机名设置 upstream
map $host $backend {default backend1; # 默认指向 backend1www.example1.com backend1;www.example2.com backend2;
}server {listen 80;location / {proxy_pass http://$backend; # 动态选择 upstream}
}
}
在这个示例中,根据 h o s t 的值, host 的值, host的值,backend 变量会被设置为 backend1 或 backend2,然后在 proxy_pass 中使用这个变量进行请求转发。
- 基于 IP 地址返回不同内容
你可以根据客户端的 IP 地址动态设置不同的响应。例如,不同的 IP 地址可能需要访问不同的区域,或者你想对某些 IP 地址进行特殊处理。
http {
# 定义基于 IP 地址的区域
map $remote_addr $access_type {
default allow; # 默认允许访问
192.168.1.100 deny; # 特定 IP 禁止访问
}
server {listen 80;location / {if ($access_type = deny) {return 403; # 如果是 deny,则返回403 Forbidden}# 正常响应return 200 "Welcome!\n";}
}
}
在这个例子中,特定的 IP 地址 192.168.1.100 将会被拒绝访问(返回 403),其他 IP 地址将会正常访问。
- 基于请求路径选择缓存策略
可以使用 map 指令根据不同的请求路径($uri)动态设置缓存时间。例如,图片和静态资源可能需要更长的缓存时间,而动态内容则不应该缓存。
http {
map $uri $cache_time {
default 0; # 默认不缓存
~^/images/ 60m; # 图片缓存 60 分钟
~^/css/ 30m; # CSS 文件缓存 30 分钟
}
server {listen 80;location / {proxy_pass http://backend;proxy_cache_valid 200 $cache_time; # 动态设置缓存时间}
}
}
在这个例子中,不同路径下的资源会有不同的缓存时间,动态资源不会被缓存,而 /images/ 下的图片会缓存 60 分钟,/css/ 下的样式表会缓存 30 分钟。
正则表达式的支持
map 指令支持正则表达式匹配条件,适合更复杂的场景。
示例:
map $host KaTeX parse error: Expected '}', got 'EOF' at end of input: …\.example1\.com backend1; # 正则表达式匹配
~^www.example2.com$ backend2;
default backend_default; # 默认值
}
• ~ 表示使用正则表达式进行匹配。
注意事项
1. 执行顺序:map 指令在 Nginx 处理请求的早期阶段执行,这意味着它的结果在整个请求过程中都可以使用,非常适合为后续指令设置变量。
2. 默认值:如果没有明确指定 default 值且没有匹配到条件,map 变量的值将为空字符串。
3. 性能:map 指令非常高效,因为 Nginx 会将 map 指令编译为内部查找表,因此即使处理大量的映射规则,性能开销也很小。
总结
Nginx 的 map 指令是一个非常灵活的工具,可以根据请求中的变量动态定义新的变量。这使得你可以根据客户端的属性(如 IP 地址、主机名、请求 URI 等)动态设置配置选项,如选择不同的后端服务器、不同的缓存策略、访问控制等。