CDN后ip_hash会导致严重流量倾斜和会话异常,因$remote_addr变为CDN节点IP,所有回源请求被哈希至同一后端;应启用real_ip_module还原真实IP并改用hash $client_ip consistent,或优先采用cookie哈希、least_conn等无状态策略。

CDN 后的客户端使用 Nginx 的 ip_hash 策略,通常会导致严重流量倾斜和会话异常——因为此时 $remote_addr 不再是用户真实 IP,而是 CDN 节点的出口 IP(如 100.64.x.x 或 203.205.x.x),所有经同一 CDN 节点回源的请求都会被哈希到同一台后端服务器。
CDN 回源使 ip_hash 失去用户粒度
CDN 作为中间代理,会把成百上千甚至上万终端用户的请求聚合到少数几个出口 IP 上发往你的 Nginx。而 ip_hash 只认 $remote_addr,结果是:
- 一个 CDN 节点(比如北京机房)的所有回源请求,全部落到 upstream 中固定某一台后端
- 其他后端节点长期空闲,CPU、连接数、缓存命中率严重不均
- 日志中高频出现的
$remote_addr集中在极少数地址(如100.64.12.33、100.64.45.88)
真实影响不止是负载不均
这种“伪一致性”还会引发连锁问题:
-
会话中断:用户从北京 CDN 切换到上海 CDN,
$remote_addr变更 → 哈希结果跳变 → 后端内存 Session 丢失 - 缓存失效加剧:相同 URL 请求因 CDN 出口不同,被分到不同后端 → 各自建本地缓存,无法复用
- 限流/风控误判:同一 CDN IP 下大量用户被识别为“单个高危 IP”,触发错误拦截或封禁
- 延时毛刺集中:某台后端因过载响应变慢,所有经该 CDN 节点的请求 P99 延时同步飙升
正确做法:用真实 IP 替代 $remote_addr 做哈希
不能直接依赖 ip_hash,而应还原并使用用户真实 IP:
- 在
http块中启用 real_ip 模块:set_real_ip_from 100.64.0.0/10; # 阿里云 CDN 段set_real_ip_from 203.205.0.0/16; # 腾讯云 CDN 段real_ip_header X-Forwarded-For; - 定义真实 IP 变量(兼容多层 CDN):
map $http_x_forwarded_for $client_ip { "" $remote_addr; ~^(?P<ip>[0-9.]+) $ip; }</ip> - 改用
hash $client_ip consistent;替代ip_hash,支持平滑扩缩容
更优替代方案(推荐优先考虑)
若业务已支持无状态或分布式 Session,应逐步淘汰基于 IP 的粘性策略:
-
登录态用户:用
hash $cookie_sessionid;,绑定到用户级标识 -
未登录访客:用
least_conn或加权轮询,配合后端共享缓存 -
静态资源 / API 分离:通过
map按$request_uri或$host分流,各自配置合适策略


















