nginx可通过geo+map+双upstream实现ip段级ip_hash控制:先用geo标记指定ip段为$use_ip_hash=1,再用map映射$backend_upstream变量,分别指向启用ip_hash或轮询的upstream块,最后在proxy_pass中引用该变量完成动态路由。

Nginx 的 ip_hash 本身只支持对整个客户端 IP 做哈希,不支持按 IP 段“选择性启用”。但可以通过 map + split_clients(不推荐)或更可靠的方式:**结合 geo 指令预标记 IP 段,再用 map 控制 upstream 的选择逻辑**,最终在 upstream 块中对特定 IP 段启用 ip_hash,其余走轮询或其他策略。
用 geo 预定义 IP 段标识
先用 geo 指令为匹配的 IP 段设置一个变量(如 $use_ip_hash),值为 1 表示该请求需走 ip_hash;其他 IP 默认为空或 0。
示例配置:
geo $use_ip_hash {
default 0;
192.168.10.0/24 1;
10.0.5.0/28 1;
2001:db8::/32 1; # 支持 IPv6
}
用 map 动态选择 upstream 名称
根据 $use_ip_hash 的值,映射出不同的 upstream 名称。注意:Nginx 不允许在 upstream 指令中做条件判断,所以必须靠外部变量驱动 upstream 切换。
示例:
map $use_ip_hash $backend_upstream {
1 "api_iphash";
0 "api_roundrobin";
}
定义两套 upstream,行为分离
分别定义两个 upstream 块:一个启用 ip_hash,一个用默认轮询(或 least_conn 等)。
-
api_iphash:仅对指定 IP 段生效,内部启用ip_hash,保证同一客户端段内用户稳定落在同一后端 -
api_roundrobin:对其他所有流量使用无状态分发
配置示例:
upstream api_iphash {
ip_hash;
server 10.0.1.10:8080;
server 10.0.1.11:8080;
}
<p>upstream api_roundrobin {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
}</p>
在 server 或 location 中使用动态 upstream
在 proxy_pass 中引用 $backend_upstream 变量(Nginx 1.3.11+ 支持变量 proxy_pass):
server {
listen 80;
location /api/ {
proxy_pass http://$backend_upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
注意:使用变量 proxy_pass 时,不能带 URI 路径(如 http://$upstream/api 是非法的),应确保后端能正确处理原始路径,或用 rewrite 统一处理。











