核心是用一致性哈希(consistent_hash $request_uri)将同一静态资源稳定映射至固定后端节点,配合gzip_static预压缩、固化缓存键(忽略accept-encoding)及规避误配陷阱,确保cdn/反向代理缓存一致性。

核心是让同一静态资源(如 /static/logo.png)在所有后端节点上命中相同的缓存副本,避免重复回源、内容不一致或 CDN 缓存分裂。关键不在“负载均衡”本身,而在如何把请求稳定地导向同一台后端——这靠一致性哈希实现。
用 consistent_hash 固定资源到后端节点
这是最直接有效的方案,尤其适合静态资源缓存场景:
- 必须使用第三方模块
ngx_http_upstream_consistent_hash,配置前先确认已编译:nginx -V 2>&1 | grep -o with-http_upstream_consistent_hash - 只允许单变量参数,推荐用
$request_uri(含查询参数),它天然绑定资源粒度;
若参数无关(如?utm_source=xxx或&_t=123),需先用map过滤归一化 - 不能和
ip_hash、hash $uri(官方 hash 模块)混用,否则nginx -t直接报错 - 权重仍生效:每个
server的weight=2会按内部算法放大虚拟节点数,不是简单取模
示例配置:
upstream static_backend {
consistent_hash $request_uri;
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=2;
server 192.168.1.12:8080;
}
配合 gzip_static 实现压缩内容零歧义
动态压缩(gzip on)容易因 Accept-Encoding 差异导致同一 URI 返回不同响应体,破坏缓存一致性。改用预生成 .gz 文件更可靠:
- 提前用
gzip -k main.js生成main.js.gz,与原文件同目录、同权限、mtime 尽量一致 - 启用
gzip_static on,Nginx 自动匹配并返回 .gz 版本,同时设置Content-Encoding: gzip和正确Content-Length - 搭配
try_files $uri.gz $uri =404,确保无 .gz 文件时降级返回原始内容
注意:CDN 侧必须关闭所有自动压缩功能(如 Cloudflare 的 Auto Minify),仅作透明转发。
固化缓存键,屏蔽客户端干扰
CDN 或 Nginx 代理缓存若把 Accept-Encoding 纳入缓存键,会导致 gzip / identity 版本被当成两个资源缓存,增加维护成本且易出错:
- 在 CDN 回源配置中,强制抹除
Accept-Encoding请求头 - Nginx 回源 location 中显式定义缓存键:
proxy_cache_key "$host$request_uri";(不含$http_accept_encoding) - 这样所有对
/a.css的请求,无论浏览器是否支持 gzip,都回源取同一个缓存项,由 Nginx 内部统一决策是否返回压缩体
补充:避免常见误配陷阱
这些细节看似小,但极易导致一致性失效:
-
$request_uri区分大小写和 URL 编码,确保前端请求格式统一(如统一小写、避免空格编码为+而非%20) - 不要用
$host或$http_referer做哈希变量:多域名共用 upstream 时会重复缓存;referer 极不稳定 - 大文件(如视频分片)若支持 range 请求,建议哈希时包含关键参数,例如:
map $request_uri $cache_key { ~^(?<base>.+)\?range=(?<range>.+)$ "$base?range=$range"; default $request_uri; }</range>
再用consistent_hash $cache_key - 模块未启用时
nginx -t不报错,但 reload 后完全不生效——这是最隐蔽的坑











