ip_hash本质是通过客户端ip哈希实现请求固定路由以缓解session丢失,并非真正共享;需满足ip与后端列表稳定、正确还原真实ip、禁用weight等参数、仅用于http upstream等前提,否则失效。

在 Nginx 中用 ip_hash 解决分布式 Session 痛点,本质不是真正“共享 Session”,而是让同一客户端 IP 的请求始终落到同一台后端服务器上,从而避免因路由跳变导致的内存 Session 丢失。它轻量、无需额外组件,但必须严格满足前提条件,否则会失效。
基础配置:upstream 块里加一行就生效
只需在 upstream 块第一行写 ip_hash;,且确保后端至少有两台真实服务器(不能只写 localhost 或单节点):
-
upstream必须显式列出多台后端,例如:server 10.0.1.10:8080; -
ip_hash;必须顶格写在upstream块最开头,不能缩进,也不能和hash $cookie_jsessionid等其他 hash 指令共存 - 每台
server行只写IP:PORT,不加http://、路径或协议头 - 不支持
weight、backup、down等参数;加了会导致 Nginx 启动失败
真实 IP 是前提:代理链下必须还原原始地址
如果前端有 CDN、WAF、Nginx 代理或多层 LB,$remote_addr 默认是上一跳地址,所有请求会被哈希到同一台后端——等于没配。
- 在
http块中启用real_ip_module,声明可信代理网段:set_real_ip_from 192.168.0.0/16;、set_real_ip_from 10.0.0.0/8; - 指定从哪个 Header 读取原始 IP:
real_ip_header X-Forwarded-For; - 在
location的proxy_pass前透传真实 IP:proxy_set_header X-Real-IP $remote_addr;、proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
避开常见失效场景
看似简单,但几个硬性限制极易导致“配了没用”:
- IPv4 地址仅取前三段哈希(如
192.168.1.100和192.168.1.255被视为同一个 IP),内网 NAT 或运营商共享出口时会造成单台过载 - 后端列表增删或顺序变动(比如扩容一台、临时
down一台),整个哈希映射关系重算,大量用户 Session “漂移” - 仅适用于 HTTP 层的
upstream;TCP/UDP 四层转发需改用stream模块 +hash $remote_addr consistent; - IPv6 完整哈希,但 Nginx 版本低于 1.7.2 可能退化为轮询,建议确认版本并查日志验证
更稳的演进方向
当业务增长、出现 NAT 干扰或频繁扩缩容时,应逐步过渡到解耦方案:
- 改用 Cookie 哈希:
hash $cookie_JSESSIONID consistent;,抗代理和 NAT 更强 - 后端统一接入 Redis 存储 Session(如 Spring Boot 配
spring.session.store-type=redis),彻底解除路由与状态绑定 - 对对象存储类服务(如 MinIO 分片上传),
ip_hash反而是合理选择,因其操作天然需要节点一致性











