ip_hash与keepalive叠加会放大负载不均、会话漂移和资源僵死问题;关键排查点是验证哈希是否按真实客户端ip生效及长连接是否破坏均衡逻辑。

ip_hash 和 keepalive 长连接本身不直接“冲突”,但二者叠加使用时会放大负载不均、会话漂移和资源僵死等隐性问题。排查关键不是找语法错误,而是验证“哈希是否真按预期工作”+“长连接是否在悄悄破坏均衡逻辑”。
确认 ip_hash 是否真正生效
很多问题根源是 $remote_addr 没还原为真实客户端 IP,导致所有请求被哈希到同一台后端:
- 检查 access log 中是否记录了真实公网 IP:在 log_format 里加入 $remote_addr 和 $upstream_addr,对比多条请求是否来自不同 IP 却落到同一 upstream 地址
- 若前端有 CDN 或 LB,必须配置 set_real_ip_from + real_ip_header X-Forwarded-For,否则 ip_hash 实际哈希的是代理 IP
- 验证 IPv4 哈希粒度:192.168.1.100 和 192.168.1.200 会被视为同一 IP(仅取前三段),在 NAT 环境下必然集中——这不是 bug,是设计行为
识别 keepalive 导致的连接级失衡
轮询或 ip_hash 都只控制新请求分发,不感知后端已建立的长连接数量。一个 TCP 连接复用上百次请求,日志里却只显示“1 条连接”,极易误判:
- 在后端机器上执行 ss -tnp | grep :port | wc -l,统计每台节点 ESTAB 状态连接数,看是否严重倾斜(如 80% 连接集中在一台)
- 在 Nginx 日志中提取 $upstream_addr 并去重统计“独立连接对”(IP:PORT),而非请求数;若某 backend 出现频率远高于其他,说明长连接滞留未释放
- 临时关闭 keepalive:在 location 中加 proxy_http_version 1.1; proxy_set_header Connection '';,观察连接分布是否趋于均匀
检查配置组合是否自相矛盾
某些看似合理实则互斥的配置,会让 ip_hash 失效或加剧风险:
- ip_hash 与 keepalive 共存时,扩容缩容必引发大规模漂移:增删 upstream server 会导致全量哈希重散列,所有长连接瞬间失效
- ip_hash 与 proxy_next_upstream error timeout 搭配危险:某后端短暂超时被标记 down 后,该 IP 所有请求将无法 fallback(ip_hash 不支持故障转移)
- upstream 块内写了 keepalive,但没关掉 client 到 Nginx 的 keepalive:导致 worker_connections 被大量空闲长连接占满,新请求排队甚至 503
快速验证与替代建议
不用等压测,几条命令就能判断当前是否已受干扰:
- 用固定源 IP(如 curl --interface 192.168.1.100)连续发 10 次请求,检查响应头 X-Upstream-Addr 是否始终一致 → 若不一致,ip_hash 未生效
- 用 watch 'ss -tn | grep :8080 | wc -l' 在各后端实时观察连接数变化 → 若某台持续增长且不下降,keepalive 泄漏或后端未正确 close
- 长连接场景优先考虑 consistent_hash(需模块支持)或 cookie 粘滞,它们比 ip_hash 更抗节点变动,也更适配真实用户标识











