推荐在 http 块用 map 预定义地域路径变量,配合 try_files 实现安全高效的静态资源地域分发,避免在 location 中使用 if;需正确加载 GeoIP2 模块与数据库,并配置 real_ip 处理代理 IP。

直接在 location 块里用 if 切换 root 是常见但不推荐的做法——容易出错、不可靠,且 Nginx 官方明确建议避免在 location 中大量使用 if。真正稳定高效的方式,是把地域判断逻辑提前到 http 或 server 块,用 map 构建变量,再在 location 中干净引用。
确保 GeoIP2 正确加载并提取国家码
必须在 http 块顶部完成数据库加载和变量定义,不能放在 location 里:
- 确认已安装
ngx_http_geoip2_module(旧版geoip_country已废弃,混用会报错) - 下载
GeoLite2-Country.mmdb,上传至服务器(如/www/geoip/GeoLite2-Country.mmdb) - 在
nginx.conf的http块开头添加:
geoip2 /www/geoip/GeoLite2-Country.mmdb {
$geoip2_data_country_code country iso_code;
$geoip2_data_country_name country names en;
}
用 map 定义地域对应的静态路径
map 指令必须在 http 或 server 块顶层声明,它把国家码映射成你预设的路径前缀:
- 例如,让中国用户访问
/cn/下资源,日本用户走/jp/,其余走默认/en/ - 在同一个
http块中添加:
map $geoip2_data_country_code $static_root {
default "/en";
CN "/cn";
JP "/jp";
KR "/kr";
}
这个 $static_root 就成了一个可安全用于 location 的变量。
在 location 中通过 try_files 实现路径拼接
不要改 root,而是用 try_files 动态查找带地域前缀的文件:
- 假设所有静态资源放在
/var/www/site/下,结构为:/var/www/site/cn/index.html、/var/www/site/jp/index.html等 - 在站点
server块内写:
location / {
alias /var/www/site/;
try_files $static_root$uri $static_root$uri/ /en$uri /en$uri/ =404;
}
这样请求 /logo.png 会依次尝试:/cn/logo.png → /jp/logo.png → /en/logo.png,命中即返回。
注意真实 IP 和调试验证
如果 Nginx 前有 CDN 或负载均衡,$remote_addr 会变成代理 IP,导致地域识别失败:
- 在
http块添加:set_real_ip_from 103.21.244.0/22;(填你实际 LB 的网段) - 并设置:
real_ip_header X-Forwarded-For; - 加个测试
location快速验证是否生效:location /geo-test { return 200 "$geoip2_data_country_code\n"; },用curl测试返回值










