Nginx 实现基于地理位置的智能近源分流需分四步:1. 通过 set_real_ip_from 等指令还原真实客户端 IP;2. 加载 GeoIP2 数据库提取国家、城市等字段;3. 用 map 指令将地域映射到 upstream 集群;4. 在 proxy_pass 中引用变量完成路由,全程无需 Lua,纯原生稳定运行。

1. 正确获取真实客户端 IP
如果用户经过 CDN、WAF 或 SLB,$remote_addr 就是代理 IP,GeoIP 查询必然失效。必须提前还原真实出口 IP:
- 在 http 块顶部配置可信上游网段:
set_real_ip_from 103.21.244.0/22;(填你实际使用的 CDN 或 LB CIDR) - 指定原始 IP 所在请求头:
real_ip_header X-Forwarded-For; - 启用递归解析(防多层代理污染):
real_ip_recursive on; - 加一条测试 location 验证:
location /ip { return 200 "$realip_remote_addr\n"; },访问确认返回的是真实公网 IP
2. 加载 GeoIP2 数据库并提取关键字段
推荐使用 MaxMind 的 GeoLite2-City.mmdb(比 Country 版本精度更高,支持城市与经纬度):
- 下载数据库(需注册 MaxMind 账号获取 License Key),上传至服务器如
/etc/nginx/geoip2/GeoLite2-City.mmdb - 在 http 块中加载模块与字段(注意:变量名自定义,但 source 必须指向真实 IP):
geoip2 /etc/nginx/geoip2/GeoLite2-City.mmdb {<br> $geoip2_data_country_code country iso_code;<br> $geoip2_data_city_name city names en;<br> $geoip2_data_latitude location latitude;<br> $geoip2_data_longitude location longitude;<br> } - 确保 nginx 已编译或安装
ngx_http_geoip2_module(Ubuntu 可装nginx-extras,CentOS 需手动编译)
3. 用 map 映射地域到就近 upstream 集群
避免在 location 或 if 中做判断——性能差、易出错、难维护。应统一在 http 块用 map 预计算:
- 定义国家码 → 后端集群名称的映射:
map $geoip2_data_country_code $backend_cluster {<br> default "us_backend";<br> CN "sh_backend";<br> JP "tk_backend";<br> KR "seoul_backend";<br> DE "frankfurt_backend";<br> BR "sp_backend";<br> } - 支持更细粒度?可拼接省/州代码:
$geoip2_data_country_code$geoip2_data_subdivision_1_iso_code,例如CN-BJ、US-CA - 务必设
default分支,覆盖未识别 IP(如私有地址、数据库未覆盖地区),防止 502
4. 定义 upstream 并完成 proxy_pass 路由
每个 upstream 对应一个物理区域的后端服务集群,Nginx 自动按变量选择:
- 在 http 或 upstream 块中声明集群:
upstream sh_backend {<br> server 192.168.10.10:8080 max_fails=2 fail_timeout=30s;<br> server 192.168.10.11:8080 max_fails=2 fail_timeout=30s;<br> }
其他集群同理(tk_backend、frankfurt_backend 等) - 在 server 或 location 中直接引用:
location / {<br> proxy_pass http://$backend_cluster;<br> proxy_set_header X-Client-Country $geoip2_data_country_code;<br> proxy_set_header X-Client-City $geoip2_data_city_name;<br> } - 建议开启健康检查(keepalive、max_fails)并配合
proxy_next_upstream实现自动故障转移


















