ip_hash不解决session共享,只通过ip哈希实现会话保持:固定同一客户端至同一后端以避免登录态丢失;需顶格置于upstream首行、至少两台后端、禁用weight等参数,并配合real_ip_module还原真实ip。

ip_hash 不解决登录态丢失的根本问题,它只是让同一客户端始终访问同一台后端服务器,从而“避免登录后跳回登录页”——前提是 Session 本身没被清理、也没被其他节点覆盖。它不共享 Session,只做会话保持。
基础配置必须写对
ip_hash 必须放在 upstream 块的第一行,顶格书写,不能缩进,也不能和其它 hash 指令(如 hash $cookie_jsessionid)共存:
- upstream 至少定义两台可用后端,单节点配 ip_hash 无意义
- server 行只写 IP:PORT,例如 server 10.0.1.10:8080;,不能加 http://、weight、backup 或 down
- IPv4 地址默认取前 3 段哈希(192.168.1.x 视为相同),IPv6 用完整地址
真实 IP 必须能还原出来
如果前面有 CDN、WAF、Nginx 代理或多层 LB,$remote_addr 默认是上一跳地址,所有请求哈希结果都一样,全打到同一台后端。必须启用 real_ip_module:
- 在 http 块中声明可信代理网段:set_real_ip_from 10.0.0.0/8;、set_real_ip_from 192.168.0.0/16; 等(按你实际部署的代理出口 IP 精确填写)
- 指定原始 IP 所在 Header:real_ip_header X-Forwarded-For;(Cloudflare 用户改用 CF-Connecting-IP)
- 开启递归解析:real_ip_recursive on;,自动跳过不可信中间 IP,取最左侧可信地址
- 在 proxy_pass 的 location 中透传:proxy_set_header X-Real-IP $remote_addr; 和 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
常见失效原因要避开
配了 ip_hash 却还是登录态丢失,大概率掉进了这些坑:
- 内网 NAT 环境下几十人共用一个出口 IP(如 10.0.0.1),全部路由到同一台后端,造成单点过载甚至超时
- 用户切换 WiFi/4G/5G,或运营商 NAT 轮转,导致真实 IP 变更,哈希映射跳转,Session 无法跟随
- 扩容缩容或临时下线一台 server,upstream 列表变化 → 哈希空间重分布 → 大量用户“漂移”,原 Session 丢失
- 误在 server 行加 weight 参数,Nginx 启动直接失败,配置根本没生效
比 ip_hash 更稳的过渡方案
当业务开始增长或移动端用户变多,建议尽快替换 ip_hash:
- 改用 hash $cookie_JSESSIONID consistent;:基于 Cookie 哈希,不受网络切换影响,扩缩容时漂移更少
- 后端登录成功后,在响应头设置 Set-Cookie: JSESSIONID=xxx; Path=/; HttpOnly; Secure,确保前端携带
- 若暂无法改造后端,可配合轻量 Session 备份:登录后把 Session ID 同步写入 Redis(TTL 同 Session),故障跳转时尝试按 Cookie 查 Redis 恢复











