Nginx基于GeoIP2实现地理位置就近路由:加载GeoLite2-City.mmdb数据库,用map按国家代码映射后端集群,结合real_ip_header确保真实IP识别,并通过日志验证与定期更新数据库保障准确性。

在 Nginx 中实现基于地理位置的就近路由,核心是通过 GeoIP(或 GeoIP2)模块获取客户端 IP 所属国家、城市甚至经纬度,再结合 map、split_clients 或 upstream 动态选择后端节点。现代推荐使用 GeoIP2 模块 + MaxMind GeoLite2 数据库,因其精度高、更新及时、支持 IPv6。
安装并启用 GeoIP2 模块
Nginx 官方不内置 GeoIP2,需编译时添加或使用预编译支持该模块的发行版(如 nginx-plus,或 Ubuntu/Debian 的 nginx-extras 包)。确认已安装:
- 安装 MaxMind GeoLite2 免费数据库(需注册账号下载
GeoLite2-Country.mmdb和GeoLite2-City.mmdb) - 在
nginx.conf的http块中加载模块与数据库:
$geoip2_data_country_code country iso_code;
$geoip2_data_city_name city names en;
$geoip2_data_latitude location latitude;
$geoip2_data_longitude location longitude;
}
用 map 指向不同区域的上游集群
定义地理区域到后端集群的映射关系,例如按国家分发到就近机房:
default "us_cluster";
CN "sh_cluster";
JP "tk_cluster";
DE "fr_cluster";
BR "sp_cluster";
}
然后在 server 块中使用:
upstream sh_cluster { server 10.0.1.10:8080; }upstream tk_cluster { server 10.0.2.10:8080; }
...
location / {
proxy_pass http://$backend_upstream;
proxy_set_header X-Client-Country $geoip2_data_country_code;
}
进阶:按城市距离做加权负载或重定向
若需更精细控制(如优先选直线距离最近的数据中心),可借助 Lua(OpenResty)或外部服务计算距离。但纯 Nginx 下可简化为“城市名匹配 + fallback”:
- 用
$geoip2_data_city_name匹配常见大城市(如 Beijing、Shanghai、Tokyo) - 对未匹配城市,降级到所属国家集群(如
map嵌套或用if+set备用逻辑) - 如需 HTTP 重定向而非反向代理,可用
return 302 https://$city_subdomain.example.com$request_uri;配合变量构造子域名
注意事项与调试技巧
GeoIP 结果依赖客户端真实 IP,务必确保:
– 启用 real_ip_header X-Forwarded-For; 并配置 set_real_ip_from 信任代理段
– 日志中加入 $geoip2_data_country_code $geoip2_data_city_name 方便验证
– 数据库定期更新(建议每周 cron 下载新 .mmdb 并 reload Nginx)
– 注意免费版 GeoLite2 不提供 ISP 或精准行政区划,商用场景建议订阅付费数据库



















