ip_hash是Nginx基于客户端IP哈希实现会话保持的负载均衡策略,支持IPv4/IPv6,但不支持权重、backup,仅限HTTP upstream,需注意代理场景下真实IP识别及扩容导致的会话漂移问题。

在 Nginx 中,ip_hash 是一种简单有效的负载均衡策略,用于将同一客户端 IP 的请求始终转发到后端同一台服务器,适用于需要会话保持(session stickiness)但又不想依赖外部 session 存储的场景。它不是“固定客户端访问”的万能解,而是基于客户端 IPv4 或 IPv6 地址哈希后做路由,天然具备一致性。
ip_hash 的工作原理与前提条件
ip_hash 会对客户端的源 IP 地址进行哈希计算(IPv4 取前 3 段,IPv6 使用完整地址),再对后端服务器数量取模,从而决定请求分发到哪一台。这意味着:
- 只要客户端 IP 不变、后端服务器列表不变(增删机器会破坏哈希映射),请求就总落在同一台 server 上
- 不支持权重(weight)、backup 等参数,开启 ip_hash 后这些配置会被忽略
- 仅适用于 HTTP upstream 块,不能用于 stream(TCP/UDP)模块(stream 模块需用
hash $remote_addr consistent;替代) - 若客户端经多层代理(如 CDN、LVS、Nginx 反向代理),真实 IP 可能被覆盖,需配合
set_real_ip_from和real_ip_header正确识别原始 IP
基础配置示例:启用 ip_hash 实现会话绑定
以下是一个典型的 upstream + ip_hash 配置片段:
upstream backend_servers {
ip_hash;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
server {
listen 80;
location / {
proxy_pass http://backend_servers;
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 块首行或紧随其后,且不能与其他 hash 类指令(如 hash $cookie_jsessionid;)共存。
常见问题与避坑指南
实际部署中容易踩的几个坑:
- IPv6 客户端行为差异:Nginx 1.7.2+ 才完整支持 IPv6 地址哈希;旧版本对 IPv6 客户端可能退化为轮询,建议升级并确认日志中 client IP 解析正确
- 运营商 NAT 导致“伪共享 IP”:校园网、移动网络常存在大量用户共用出口 IP,此时 ip_hash 会造成后端某台机器流量激增,应结合业务容忍度评估是否适用
-
后端扩容/缩容引发会话漂移:增加或下线一台 server 会改变取模基数,导致大部分已有客户端被重新分配。生产环境如需弹性伸缩,建议改用一致性哈希(
hash $remote_addr consistent;)或引入 Redis 共享 session -
日志验证是否生效:在 access_log 中加入
$upstream_addr变量,观察同一 IP 的多次请求是否始终命中相同后端地址
替代方案对比:什么情况下不该用 ip_hash
当出现以下任一情况时,应考虑其他机制:
- 客户端 IP 高频变化(如移动端频繁切换 Wi-Fi/4G、使用代理池)→ 改用 cookie hash(
hash $cookie_route;)或 token 透传 - 需要按权重分配流量,同时保留部分粘性 → 使用
least_conn或random two least_conn;配合应用层 session 复制 - 后端是无状态服务,且 session 已存于 Redis/DB → 直接关闭粘性,用 round-robin 更利于负载均衡
- 必须支持 TCP 层长连接粘性(如 WebSocket、MySQL 代理)→ 在 stream {} 块中使用
hash $remote_addr consistent;











