ip_hash必须位于upstream块顶层且仅出现一次,不可缩进、不可与weight/backup/其他hash指令共存;需配合real_ip_module还原真实ip,否则代理环境下会失效。

ip_hash 指令必须直接写在 upstream 块的顶层,不能嵌套在 server、keepalive 或其他指令内部,也不能出现在 http、server 等非 upstream 上下文中。书写位置错误会导致 Nginx 启动失败或配置被静默忽略,这是最常见的故障根源。
检查 ip_hash 是否位于 upstream 块最外层
ip_hash 必须和 server 指令同级,且只能出现一次。以下写法是错误的:
- 放在 server 行后面(如 server 192.168.1.10:80 ip_hash;)→ 语法错误,Nginx 拒绝加载
- 缩进在某个条件块或注释后(如带空格/制表符开头)→ 可能被解析为无效指令,报 “unknown directive”
- 重复出现两次 → 第二个会被忽略,但日志中可能无提示,导致负载不均却难以察觉
确认 upstream 块未启用不兼容特性
ip_hash 与以下配置互斥,共存会触发启动失败或行为异常:
- least_conn、hash $uri、random 等其他负载均衡算法 → Nginx 启动时报 “invalid number of arguments in 'upstream' directive” 或直接退出
- keepalive 指令本身不冲突,但若搭配了 proxy_http_version 1.1 + Connection: keep-alive 的后端,需确保客户端 IP 在代理链中未被覆盖(如没配 proxy_set_header X-Real-IP)
- zone 指令(用于动态 upstream)→ ip_hash 不支持共享内存 zone,会报错 “ip_hash is not allowed when upstream has a zone”
验证客户端 IP 是否真实传递
ip_hash 实际哈希的是 $remote_addr 变量。如果前端有 CDN、反向代理或 LVS,$remote_addr 会变成代理 IP,导致所有用户被分到同一台后端。
- 检查 access_log 中每条请求的 $remote_addr 值是否为真实用户 IP
- 若使用了 proxy_protocol 或 X-Forwarded-For,需配合 set_real_ip_from + real_ip_header 使用,否则 ip_hash 失效
- 可在 location 中临时加 log_format 输出 $remote_addr 和 $http_x_forwarded_for 对比验证
用 nginx -t 和错误日志快速定位
不要依赖 reload,先用语法检查和日志交叉验证:
- 运行 nginx -t:直接暴露 “unknown directive ‘ip_hash’” 或 “directive is not allowed here” 类错误
- 查看 error.log(默认 /var/log/nginx/error.log):搜索 “upstream”、“ip_hash”、“invalid”,常见提示如 “ip_hash requires at least one server”(upstream 内无 server)
- 成功加载后,用 curl -I 多次访问,观察 Set-Cookie 或响应头中的后端标识是否稳定 —— 若频繁切换,说明 ip_hash 未生效











