开启 gzip_vary on 不足以确保传统 cdn 正确分发压缩资源,因其仅在实际压缩时添加 vary: accept-encoding;必须配合 add_header vary accept-encoding 强制所有响应携带该头,才能使 cdn 按 accept-encoding 拆分缓存键。

开启 gzip_vary on 是让 Nginx 在启用 gzip 压缩时自动添加 Vary: Accept-Encoding 响应头的基础操作,但仅靠这一项不足以确保传统 CDN 节点正确识别和分发压缩资源——关键在于“所有响应都必须带这个头”,而 Nginx 默认行为只在实际压缩时才加,未压缩响应会漏掉,导致缓存混淆。
为什么 gzip_vary on 单独不够
Nginx 的 gzip_vary on 是条件触发的:只有当请求带 Accept-Encoding: gzip 且响应内容匹配 gzip_types、长度超过 gzip_min_length 时,才会插入 Vary: Accept-Encoding。如果某个请求没声明支持压缩(比如爬虫、旧工具、监控探针),Nginx 不压缩,也不加 Vary 头。CDN 就会把这次响应当作“通用版本”缓存,后续有支持 gzip 的用户来访问,可能拿到未压缩内容,造成 JS 执行失败或页面空白。
必须显式补全 Vary 头,覆盖全部响应
要在所有 HTTP 响应中强制带上 Vary: Accept-Encoding,无论是否压缩,需在配置中明确添加:
gzip on;gzip_vary on;add_header Vary Accept-Encoding;
注意:add_header 必须写在 gzip on 之后,且不能被 proxy_hide_header Vary 或类似指令覆盖。它会覆盖 Nginx 的条件性行为,确保每个响应都有统一标识,CDN 才能按 Accept-Encoding 值拆分缓存键。
Nginx是一款高性能的开源软件,由俄罗斯开发者Igor Sysoev于2004年创建。它最初设计为高效的HTTP Web服务器,现已成为最受欢迎的Web服务器之一。Nginx以事件驱动、非阻塞I/O架构著称,能以极低内存占用处理数万并发连接,特别适合高流量场景。它同时担任反向代理、负载均衡器、HTTP缓存、TCP/UDP代理等多重角色,常用于静态文件服务、SSL终止、请求转发、API网关和微服务
验证 CDN 是否真正识别 Vary
用两条 curl 命令对比测试同一资源:
-
curl -H "Accept-Encoding: gzip" -I https://example.com/main.js→ 应返回Content-Encoding: gzip和Vary: Accept-Encoding -
curl -H "Accept-Encoding:" -I https://example.com/main.js→ 应返回无Content-Encoding,但Vary: Accept-Encoding仍存在
若两次响应的 Vary 头不一致,或第二次缺失,说明配置未生效;若 CDN 返回的 Age 值相同,大概率是它没解析 Vary,仍在用 URL 单一缓存键。
适配不同传统 CDN 的关键设置
光 Nginx 加头没用,CDN 层必须配合解析:
- Cloudflare:默认尊重 Vary,但需关闭「Cache Everything」策略,否则会强制忽略 Vary
- AWS CloudFront:在缓存策略中必须勾选 “Include Accept-Encoding in cache key”
- 自建或白牌 CDN:确认其缓存模块支持 Vary 解析;若只做简单 URL 哈希,需升级或切换为支持多维缓存键的引擎
若 CDN 不支持或未启用 Vary 解析,再严格的 Nginx 配置也无效——此时应考虑预压缩 + gzip_static on,并手动为 .gz 文件响应补 Vary 头。










