Nginx可基于GeoIP2实现地理分流:先通过set_real_ip_from等配置获取真实IP,再用geoip2模块匹配国家/城市,最后用map预定义后端路由,需设置default兜底并记录日志验证。

利用 Nginx 实现基于地理位置的 IP 流量分流,核心在于获取客户端真实 IP,并结合 GeoIP 或 GeoIP2 数据库匹配其所属国家、省份甚至城市,再依据匹配结果将请求路由到不同后端服务。这不需要额外网关组件,纯 Nginx 即可完成,但需注意数据精度、性能开销与配置细节。
启用真实 IP 识别(关键前提)
若 Nginx 前有 CDN、SLB 或反向代理,$remote_addr 将是上游节点 IP,必须通过 X-Forwarded-For 或 Real-IP 头还原用户真实 IP。需在 server 或 http 块中配置:
- 使用 set_real_ip_from 明确可信上游网段(如 CDN 回源段、公司内网段)
- 配合 real_ip_header X-Forwarded-For 和 real_ip_recursive on 正确提取最左有效 IP
- 验证是否生效:在日志中添加
$realip_remote_addr字段,对比是否为用户真实出口 IP
集成 GeoIP2(推荐,精度高且持续更新)
GeoIP2 是 MaxMind 提供的现代地理数据库,比旧版 GeoIP 更准确、支持城市级定位。需编译安装 nginx-module-geoip2 模块(官方源或 OpenResty 已内置),并在 http 块加载数据库:
- 下载
GeoLite2-Country.mmdb和/或GeoLite2-City.mmdb(免费版需注册获取 License Key) - 配置:
geoip2 /path/to/GeoLite2-City.mmdb { $geoip2_data_country_code source=$remote_addr country iso_code; $geoip2_data_city_name source=$remote_addr city name; } - 变量如
$geoip2_data_country_code可直接用于 if、map 或 proxy_pass 中
定义分流策略(灵活匹配 + 避免硬编码)
不建议在 location 或 if 中大量写条件判断,应优先用 map 指令预计算目标 upstream 或路径前缀,提升性能和可维护性:
- 例如:
map $geoip2_data_country_code $backend_upstream { default "default_backend"; CN "cn_backend"; JP "jp_backend"; US "us_backend"; } - 再在 proxy_pass 中引用:
proxy_pass http://$backend_upstream; - 支持多级组合:用
$geoip2_data_country_code$geoip2_data_subdivision_1_iso_code匹配“CN-BJ”“US-CA”等更细粒度区域 - 对未命中或私有 IP(如 10.0.0.0/8),确保 map 有 default 分支,避免 502
验证与兜底(上线前必做)
地理库无法覆盖全部 IP,尤其新分配地址、移动运营商出口、隐私代理等场景。需设计可观测性和降级机制:
- 在 access_log 中记录
$geoip2_data_country_code和$upstream_addr,定期统计未匹配率 - 对空值或未知国家(如 “ZZ”),统一 fallback 到默认集群,而非报错或中断
- 用 curl 模拟不同地区请求:
curl -H "X-Forwarded-For: 203.123.45.67" http://your.domain/(配合测试 IP) - 注意:GeoIP 查询有轻微 CPU 开销,高并发下建议开启 shared memory 缓存(模块支持)

















