Nginx 实现基于地理位置的智能分流需 DNS 与 Nginx 协同:DNS 按国家/省份粗粒度分发至地域 VIP,Nginx 用 GeoIP2 模块在本地集群内按省/市/运营商细粒度路由;二者互补,缺一不可。

要让 Nginx 实现基于客户端地理位置的智能分流,不能只靠 DNS 或只靠反向代理单一层级——它需要DNS 做全局入口调度 + Nginx 做本地精细化路由,两者配合才能兼顾覆盖广度与响应精度。
DNS 层:实现跨区域粗粒度分流
DNS 是用户请求最先触达的环节,适合做第一层地理分发。关键不是“解析快”,而是“返回离用户最近的接入点”:
- 在权威 DNS(如阿里云云解析、AWS Route 53)中配置 GeoLocation 策略,按国家/省份返回不同机房的 VIP 地址
- 例如:北京用户访问时返回
103.21.244.10(华北 Nginx 入口),东京用户返回203.107.128.5(日韩集群入口) - TTL 设为 60–300 秒,兼顾缓存效率与故障切换速度;必须开启健康探测,自动屏蔽宕机节点
Nginx 层:完成同机房内细粒度近源路由
当流量已进入某地域 Nginx 集群后,再用 GeoIP2 模块做二次决策,把请求导向该机房内更优的后端节点:
- 先确保获取真实客户端 IP:
set_real_ip_from声明 CDN/LB 网段,real_ip_header X-Forwarded-For并启用real_ip_recursive on - 加载 GeoIP2 数据库,提取
$geoip2_data_country_code或$geoip2_data_city_name - 用
map指令将地域映射到 upstream 名称,比如中国 →backend_cn,美国 →backend_us - 在
proxy_pass中引用变量:proxy_pass http://$upstream_cluster;,不写 if,不调 Lua
为什么不能只靠其中一种?
DNS 无法识别同一城市内不同运营商(如联通 vs 移动)的网络质量差异,也难以处理 CDN 回源链路异常;而纯 Nginx 路由无法跨地域调度,若华北机房整体过载,它无法把部分北京用户导去华东。二者是互补关系:
- DNS 解决“去哪个大区”的问题,延迟毫秒级,影响首次连接
- Nginx 解决“在本区选哪台服务器”的问题,毫秒级内完成,影响后续所有请求
- 真实生产环境通常两级联动:DNS 分到三线机房 → Nginx 再按省/市/运营商做二次分发
验证与灰度要点
上线前必须验证链路是否完整:
- 用
curl -H "X-Forwarded-For: 203.107.128.1" http://your-domain.com/ip测试 GeoIP 提取是否准确 - 在 Nginx 日志中添加
$geoip2_data_country_code $upstream_cluster字段,观察映射是否符合预期 - 灰度发布时,可先对 5% 的海外 IP 强制走国内 upstream,验证 fallback 逻辑是否健壮



















