ip_hash失效主因是配置位置错误、真实IP被代理覆盖、upstream变动或后端干扰;须确保ip_hash在upstream块内、还原真实IP、避免动态变更节点,并排查后端session机制。

当 Nginx 本身作为上层代理(比如被另一个 Nginx、SLB 或 CDN 代理)时,它收到的 $remote_addr 就不再是用户真实 IP,而是上游代理的内网 IP。此时 ip_hash 会基于这个固定 IP 计算哈希,所有请求都落到同一台后端,造成“HASH 失效”——本质不是算法坏了,而是输入错了。
确认 Nginx 收到的是不是真实客户端 IP
先验证问题根源:在 access_log 中加入 $remote_addr 和 $http_x_forwarded_for 对比查看
- 如果
$remote_addr总是同一个内网地址(如10.0.1.5或172.16.0.2),说明前端有代理且未透传真实 IP - 如果
$http_x_forwarded_for里有多个逗号分隔的 IP(如203.12.45.8, 10.0.1.5),最左边才是用户真实 IP
配置 real_ip 指令还原真实 IP
必须在 http 或 server 块中声明可信代理段,并指定头字段来源
-
set_real_ip_from要明确列出上游代理的 CIDR 网段(如10.0.0.0/8、172.16.0.0/12、192.168.0.0/16),不能写0.0.0.0/0 -
real_ip_header X-Forwarded-For表示从该 HTTP 头取原始 IP;若上游用X-Real-IP,则改用对应字段 - 开启
real_ip_recursive on可逐层剥离代理 IP,取最外层真实值(推荐启用)
检查 ip_hash 是否作用在正确的 upstream 块内
ip_hash 生效前提是它被正确解析并绑定到 upstream 实例
- 确保
ip_hash;直接写在upstream { ... }内部,不在 location 或 server 块里 - upstream 中不能混用
weight、max_fails、backup等参数(新版本会报错,旧版本静默忽略) - 避免使用
resolve动态 DNS 或运行时增删 server —— 节点列表变动会重置哈希映射
验证 $remote_addr 是否已更新为真实 IP
加一条临时日志或返回头,确认 real_ip 配置是否生效
- 在 location 中添加:
add_header X-Debug-Remote-Addr $remote_addr; - 用 curl 请求,观察响应头中的值是否变成公网 IP(而非内网地址)
- 若仍是内网 IP,说明
set_real_ip_from范围没覆盖上游代理,或对方未发送X-Forwarded-For


















