ip_hash是nginx原生会话保持方案,需在upstream块首行配置,仅支持http、不兼容weight/backup,ipv4取前三段哈希,代理环境须用real_ip_module还原真实ip。

直接在 upstream 块开头加 ip_hash; 即可实现基于客户端源 IP 的会话保持,但必须配合真实 IP 识别、避开 NAT 干扰和后端稳定性设计,否则容易“配了没用”。
基础配置写法(必须严格遵循)
ip_hash 只能放在 upstream 块第一行,不能缩进,不能和其他 hash 指令混用:
- upstream 必须定义至少两台后端(不能只写 localhost 或单节点)
- server 行只写
IP:PORT,不加http://或路径 - 不支持
weight、backup、down等参数;加了会导致 Nginx 启动失败
示例:
upstream backend {ip_hash;
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
确保拿到真实客户端 IP
如果前端有 CDN、WAF、Nginx 代理或多层负载均衡,$remote_addr 默认是上一跳地址,所有请求会被哈希到同一台后端。
- 在
http块中配置可信代理段和真实头字段:set_real_ip_from 192.168.0.0/16;set_real_ip_from 10.0.0.0/8;real_ip_header X-Forwarded-For; - 在
location中透传真实 IP:proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
绕开常见失效陷阱
ip_hash 表面简单,但几个硬性限制极易导致会话漂移或负载失衡:
- IPv4 地址仅取前三段哈希(如
192.168.1.100和192.168.1.200被视为同一 IP),内网 NAT 环境下易造成单台过载 - 后端列表顺序或数量变动(如扩容、缩容、临时
down一台),所有哈希映射整体偏移,大量用户 Session “漂移” - 某台 server 标记为
down时,Nginx 会剔除它,剩余节点重新分配请求,但原有 IP 映射关系仍在剩余节点上维持
更稳的替代思路(建议业务成熟后升级)
当对可靠性要求提高,或已出现 NAT、代理、频繁扩缩容等问题时,应考虑跳出 IP 绑定逻辑:
- 改用 Cookie 哈希:
hash $cookie_JSESSIONID consistent;,抗代理和 NAT 更强 - 后端统一接入 Redis 存储 Session(如 Spring Boot 配置
spring.session.store-type=redis),彻底解耦路由与状态 - TCP/UDP 四层转发场景(如 MySQL、Redis 代理),必须用
stream模块 +hash $remote_addr consistent;,ip_hash 不生效










