如何用Nginx map模块根据IP段实现不同区域后端资源加速?
- 内容介绍
- 文章标签
- 相关推荐
本文共计937个文字,预计阅读时间需要4分钟。
很多人一上来就在+Nginx+块里写+map+,Nginx+直接报错:
实操建议:
- 把所有
map块统一放在nginx.conf的http大括号最上方(或单独 include 进来) - 每个
map必须指定源变量(如$remote_addr)和目标变量名(如$backend_group),且目标变量不能已存在 - 匹配顺序从上到下,第一个成功匹配的规则生效;用
default设兜底值,否则未匹配时变量为空字符串——这可能导致 upstream 选型失败
用 CIDR 精确匹配 IP 段,别用正则硬扛
有人试图用 ~ 正则去判断 192.168.10. 开头的地址,结果发现 $remote_addr 可能带端口(IPv6 场景)、可能被代理覆盖、还可能触发重复编译开销。正确做法是用原生 CIDR 语法,Nginx map 对 192.168.0.0/16 这类写法原生支持,无额外性能损耗。
实操建议:
- 优先使用 CIDR 表达式,例如:
114.114.114.0/24、2408:8700::/32 - 国内常见 CDN 回源 IP 段可直接查运营商公开路由表,比如阿里云函数计算回源段是
47.96.0.0/16,腾讯云是101.32.0.0/16 - 如果必须用正则(如匹配某类动态出口 IP),改用
~*不区分大小写,并确保正则足够简短,避免在每次请求时重复执行
map 变量要和 upstream name 对齐,否则 502 就在下一秒
map 本身只负责赋值,真正路由靠 proxy_pass http://$backend_group。如果 $backend_group 的值是 bj_cluster,但 upstream 块叫 upstream beijing,Nginx 启动不报错,但请求一来就是 502 Bad Gateway —— 因为它找不到名为 bj_cluster 的 upstream。
实操建议:
- upstream 名称必须与 map 输出的字符串**完全一致**(包括大小写、下划线、中划线)
- 建议命名风格统一,例如全部小写 + 下划线:
shanghai_cache、guangzhou_origin - 可以在
upstream块里加keepalive 32和least_conn,但不要在 map 里做负载逻辑——map 只管“分组”,不负责“选节点”
真实环境必须处理 X-Forwarded-For 链路污染
线上几乎全是反向代理链路,$remote_addr 拿到的是上一跳 Nginx 或 SLB 的 IP,不是真实用户 IP。直接拿它做地理分流,全国用户都会被分到同一个后端集群。
实操建议:
- 先用
set_real_ip_from明确可信代理网段(如公司内网段、云厂商 LB 段) - 再启用
real_ip_header X-Forwarded-For,让 Nginx 把$remote_addr替换为 header 最左的有效 IP - 验证是否生效:加一行
add_header X-Real-IP $remote_addr;,curl 看响应头;注意某些 CDN 会伪造 XFF,需配合real_ip_recursive on向右递归取最后一个非可信 IP
本文共计937个文字,预计阅读时间需要4分钟。
很多人一上来就在+Nginx+块里写+map+,Nginx+直接报错:
实操建议:
- 把所有
map块统一放在nginx.conf的http大括号最上方(或单独 include 进来) - 每个
map必须指定源变量(如$remote_addr)和目标变量名(如$backend_group),且目标变量不能已存在 - 匹配顺序从上到下,第一个成功匹配的规则生效;用
default设兜底值,否则未匹配时变量为空字符串——这可能导致 upstream 选型失败
用 CIDR 精确匹配 IP 段,别用正则硬扛
有人试图用 ~ 正则去判断 192.168.10. 开头的地址,结果发现 $remote_addr 可能带端口(IPv6 场景)、可能被代理覆盖、还可能触发重复编译开销。正确做法是用原生 CIDR 语法,Nginx map 对 192.168.0.0/16 这类写法原生支持,无额外性能损耗。
实操建议:
- 优先使用 CIDR 表达式,例如:
114.114.114.0/24、2408:8700::/32 - 国内常见 CDN 回源 IP 段可直接查运营商公开路由表,比如阿里云函数计算回源段是
47.96.0.0/16,腾讯云是101.32.0.0/16 - 如果必须用正则(如匹配某类动态出口 IP),改用
~*不区分大小写,并确保正则足够简短,避免在每次请求时重复执行
map 变量要和 upstream name 对齐,否则 502 就在下一秒
map 本身只负责赋值,真正路由靠 proxy_pass http://$backend_group。如果 $backend_group 的值是 bj_cluster,但 upstream 块叫 upstream beijing,Nginx 启动不报错,但请求一来就是 502 Bad Gateway —— 因为它找不到名为 bj_cluster 的 upstream。
实操建议:
- upstream 名称必须与 map 输出的字符串**完全一致**(包括大小写、下划线、中划线)
- 建议命名风格统一,例如全部小写 + 下划线:
shanghai_cache、guangzhou_origin - 可以在
upstream块里加keepalive 32和least_conn,但不要在 map 里做负载逻辑——map 只管“分组”,不负责“选节点”
真实环境必须处理 X-Forwarded-For 链路污染
线上几乎全是反向代理链路,$remote_addr 拿到的是上一跳 Nginx 或 SLB 的 IP,不是真实用户 IP。直接拿它做地理分流,全国用户都会被分到同一个后端集群。
实操建议:
- 先用
set_real_ip_from明确可信代理网段(如公司内网段、云厂商 LB 段) - 再启用
real_ip_header X-Forwarded-For,让 Nginx 把$remote_addr替换为 header 最左的有效 IP - 验证是否生效:加一行
add_header X-Real-IP $remote_addr;,curl 看响应头;注意某些 CDN 会伪造 XFF,需配合real_ip_recursive on向右递归取最后一个非可信 IP

