ip_hash通过客户端ip哈希实现会话持久化,使同一ip请求始终转发至同一后端服务器,避免session丢失;适用于内网稳定ip场景,但不支持weight、易受nat影响且扩容会导致会话漂移。

用 ip_hash 实现客户端会话持久化,核心是让同一 IP 的请求始终打到同一台后端服务器,从而避免 Session 丢失——前提是你的应用本身不依赖外部共享存储(如 Redis),且 Session 存在本地内存或文件中。
适用场景与前提条件
这个方案适合内网环境或客户端 IP 稳定的场景,比如企业内部系统、局域网测试平台、固定出口 NAT 后的办公网络。它不适用于公网移动用户、大型 CDN 接入、或频繁切换网络的终端,因为这些情况下真实 IP 可能变化或被代理覆盖。
- 后端服务必须自己管理 Session(例如 Tomcat 默认内存 Session、Spring Boot 内置 Session)
- Nginx 需正确识别客户端真实 IP,若前面有代理,要配置
set_real_ip_from和real_ip_header - IPv4 地址只取前三段哈希(
192.168.1.x全视为同一 IP),IPv6 则用完整地址(需 Nginx ≥1.19) - 后端服务器列表不能频繁增减,否则哈希映射会整体偏移,导致大量会话“漂移”
基础配置写法
只需在 upstream 块中加入 ip_hash;,其他保持常规反向代理设置即可:
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_hash必须放在upstream块靠前位置,不能和weight、backup共存 - 某台 server 被标记为
down时,Nginx 会自动剔除它,后续请求重新分配,但原有 IP 映射关系仍维持在剩余节点上 - 不支持 stream 模块(TCP/UDP),如需四层会话保持,得改用
hash $remote_addr consistent;
关键限制与应对建议
ip_hash 是简单直接的方案,但不是无痛解。几个常见问题需要提前规划:
- 单点故障风险:后端某台宕机,该 IP 段所有用户 Session 丢失,且下次请求会落到新服务器,需配合健康检查 + 应用层重登录机制
- 负载不均:内网一个大子网(如
192.168.1.0/24)的所有用户都压到同一台机器,容易造成热点 - 无法加权:不能设
weight=2这类参数;如真需权重+粘性,改用hash $remote_addr consistent;并配 weight - Cookie 更可靠:如果业务真正绑定的是登录态而非 IP,推荐改用
hash $cookie_jsessionid consistent;,抗 NAT、代理干扰更强
验证是否生效
最简单的验证方式是:用固定客户端(如一台测试机)连续发起多个请求,观察响应头中的 Server 或自定义标识(如后端返回的机器名),确认始终落在同一台;再临时停掉该服务器,看是否切换并保持新绑定。
- 注意查看 Nginx 错误日志,启动时报 “
ip_hash cannot be used with weighted servers” 就说明混用了 weight - 可通过
curl -H "X-Real-IP: 192.168.1.100" http://your-domain/模拟不同 IP 测试哈希分布 - 上线前建议做小流量灰度,观察会话中断率和后端负载曲线











