GeoIP2模块仅解析IP地理信息,差异化调度需结合map映射地理变量为上游组名,并在upstream中配置weight实现流量倾斜;动态权重需OpenResty+Lua;注意避免stream块使用、real_ip配置及数据库更新。

GeoIP2 模块本身不支持权重调度,它只负责解析 IP 地理信息并生成变量(如 `$geoip2_data_country_code`),真正的“差异化调度”需由 Nginx 的其他机制实现——核心是用 `map` 或 `if` 将地理变量转化为可参与 upstream 选择的标识,再结合 `upstream` 块中的 `weight`、`backup` 或 `slow_start` 等参数完成流量倾斜。
地理变量 + map 映射为调度键
先通过 `geoip2` 提取国家码等字段,再用 `map` 将其映射为逻辑分组名或权重系数:
- 在 `http` 块中定义地理识别与映射:
geoip2 /www/geoip/GeoLite2-Country.mmdb { $geoip2_country_code country iso_code; } map $geoip2_country_code $upstream_group { default "default_cluster"; CN "cn_cluster"; US "us_cluster"; JP "jp_cluster"; DE "eu_cluster"; } - 该 `$upstream_group` 可直接用于 `proxy_pass http://$upstream_group;`,实现基础地域分流
在 upstream 中配置权重实现流量倾斜
同一地域组内若有多个后端节点,可通过 `weight` 控制各节点承接比例;不同地域组之间也可用 `weight` 模拟“优先级”:
- 例如中国用户主走上海机房,但保留 10% 流量试探深圳节点以做灾备:
upstream cn_cluster { server 10.0.1.10:80 weight=90; server 10.0.2.10:80 weight=10; } - 若想让美国用户 70% 走美东、30% 走美西,且日本用户 100% 走东京节点,就分别定义 `us_cluster` 和 `jp_cluster` 并设置对应权重
- 注意:`weight` 是相对值,不是百分比;Nginx 按权重总和计算占比,如 `weight=7` 和 `weight=3` 即为 70%/30%
动态权重需借助 Lua(进阶场景)
纯静态配置无法根据实时指标(如延迟、负载)调整权重。若需“按地域+健康度”联合调度,必须引入 OpenResty + Lua:
- 用 `lua-resty-maxminddb` 在 `access_by_lua_block` 中读取 `$remote_addr` 对应的国家码
- 查本地缓存或 Redis 获取该国家下各集群当前 RTT 或错误率
- 动态构造 `balancer_by_lua_block`,调用 `set_current_peer()` 指向最优节点
- 这种方式绕过 `upstream` 静态权重,实现真正自适应的地域加权路由
避免常见误区
几个容易踩坑的关键点:
- 不要在 stream 块里用 geoip2:四层代理不支持该模块,强行写会启动失败
- 不要把 weight 当成绝对阈值:它影响的是轮询概率,不保证严格比例,尤其在请求数少时偏差明显
- 真实 IP 必须正确传递:CDN 或 LB 后需配置 `set_real_ip_from` 和 `real_ip_header`,否则 `$remote_addr` 是上一跳地址,地理识别失效
- 数据库要定期更新:MaxMind 免费库每月更新,建议用 cron 自动下载 `GeoLite2-Country.mmdb` 并 reload nginx










