ip_hash是Nginx原生会话保持方案,通过客户端IP哈希将请求固定分发至同一后端服务器,适用于内网IP稳定、暂无共享存储的过渡场景;需顶格配置在upstream首行,配合real_ip_module还原真实IP,并避开weight、NAT、扩缩容等导致失效的常见陷阱。

ip_hash 不是解决登录痛点的“根治方案”,而是让同一用户始终打到同一台后端,从而让 Session 有机会被命中。它适合前后端分离项目中后端尚未改造、又急需缓解“登录后刷新跳回登录页”问题的过渡阶段。
基础配置必须写对
ip_hash 必须放在 upstream 块的第一行,顶格书写,不能缩进,也不能和其他 hash 指令混用:
- upstream 至少定义两台可用后端,单节点配 ip_hash 没有意义
- server 行只写 IP:PORT,例如
server 10.0.1.10:8080;,不能加http://、weight、backup或down - IPv4 默认取前 3 段哈希(
192.168.1.x全视为相同),内网 NAT 环境下容易集中打到一台,需留意
真实 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;(按你实际出口 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 却还是反复跳登录页,大概率踩了这些坑:
- 内网几十人共用一个出口 IP(如
10.0.0.1),全部路由到同一台后端,导致超时或拒绝服务 - 用户从 WiFi 切到 4G/5G,或运营商 NAT 轮转,真实 IP 变更 → 哈希映射跳转 → Session 找不到
- 扩容缩容或临时下线一台 server,upstream 列表变化 → 哈希空间重分布 → 大量用户“漂移”
- 误在 server 行加 weight 参数,Nginx 启动失败,配置根本没生效
比 ip_hash 更稳的过渡思路
当项目开始接入移动端或用户网络环境不可控时,建议尽快升级:
- 改用
hash $cookie_JSESSIONID consistent;:基于 Cookie 哈希,不受网络切换影响;后端登录成功后需设置Set-Cookie: JSESSIONID=xxx; Path=/; HttpOnly; Secure - 轻量级 Session 同步:登录后把 Session ID 写入 Redis,各节点读取时先查缓存再查本地内存
- 前端存储 JWT,后端全部无状态校验,彻底跳出 Session 绑定服务器的逻辑


















