ip_hash在NAT场景下失效,因共享公网IP导致哈希倾斜;应优先还原真实IP(via real_ip_module),或改用cookie/token/consistent_hash等更稳定锚点,并叠加限流与监控。

直接配置 ip_hash 无法应对大规模 NAT 网关出口场景——它会把成百上千用户识别为同一个 IP,全部压向单台后端,导致严重倾斜甚至雪崩。必须放弃“只配 ip_hash”这种思路,转为组合策略还原真实标识或切换锚点。
为什么 ip_hash 在 NAT 出口下会失效
企业防火墙、校园网出口、运营商 CGNAT 都会让大量终端共享一个公网 IP(例如 203.101.5.8)。Nginx 默认用 $remote_addr 做哈希,这个值就是那个出口地址。IPv4 还只取前三段计算(如 203.101.5.x → 统一视为 203.101.5.0),进一步放大集中效应。结果是:所有请求哈希值完全一致,100% 落到 upstream 中某一台 server 上,其余节点闲置。
优先还原真实客户端 IP
若上游设备(如内网网关、WAF 或 CDN)支持透传原始 IP,可用 real_ip_module 替换 $remote_addr,让哈希基于真实地址:
- 在
http块中声明可信代理段:set_real_ip_from 10.0.0.0/8;set_real_ip_from 192.168.0.0/16;set_real_ip_from 172.16.0.0/12; - 指定提取头字段:
real_ip_header X-Forwarded-For;(或X-Real-IP,依实际透传为准)real_ip_recursive on;(防多层代理污染) - 验证是否生效:在
log_format中加入$remote_addr和$http_x_forwarded_for,比对日志确认还原准确
更可靠的替代方案:换掉 IP 这个锚点
当网络结构注定无法稳定提供唯一 IP 时,应改用业务层标识做哈希:
-
hash $cookie_session_id;:适用于已有有效 session cookie 的 Web 应用,天然具备用户粒度 -
hash $arg_token;或hash $http_authorization;:对接 JWT、OAuth 等鉴权系统,token 具备强唯一性与稳定性 -
consistent_hash $binary_remote_addr;:需 Nginx 1.19+,相比普通 ip_hash,增减后端时仅影响少量连接,适合弹性扩缩容
必须配套的防护措施
即使换了哈希方式,NAT 场景下仍可能出现突发流量打爆单点,需叠加控制:
- 用
limit_conn限制单个真实 IP(或还原后的 IP)并发连接数 - 用
limit_req控制单位时间请求数,防止单点过载 - 在 access_log 中记录
$upstream_addr和$remote_addr,定期统计各后端接收的 IP 段分布,及时发现倾斜
不复杂但容易忽略。


















