nginx缓存中vary头部必须与proxy_cache_key严格对齐,仅对真实影响响应内容的请求头设置vary;需用map归一化不稳定头(如user-agent)、统一空origin、启用gzip_vary,并用always确保全状态码输出vary。

在 Nginx 缓存中正确处理 Vary 头部,核心是让缓存键(proxy_cache_key)和响应头(Vary)严格对齐,并且只对真实影响响应内容的请求头做区分。加错、漏加或不配对,都会导致缓存命中率暴跌或内容错乱。
确保 Vary 值与缓存键变量完全一致
缓存系统靠 Vary 头告诉下游:“这个响应依赖哪些请求头”,而 Nginx 靠 proxy_cache_key 决定“存几份”。两者必须一一对应:
- 若设置
add_header Vary Origin;,缓存键里就必须含$http_origin,例如:proxy_cache_key "$scheme$request_method$host$request_uri$http_origin"; - 若用
map归一化 User-Agent 得到$device_type,并设add_header Vary "Device-Type";,那缓存键也得包含$device_type - 多个维度就写全:
add_header Vary "Origin, Device-Type, Accept-Encoding";→ 缓存键中必须同时有$http_origin、$device_type、$http_accept_encoding
避免直接使用不稳定请求头
像完整 User-Agent 或随机变化的 Referer,不能直接进 Vary,否则缓存会爆炸:
- 用
map把千变万化的 UA 映射为有限稳定值(如mobile/desktop),再基于该变量Vary - 对
Accept-Encoding,启用gzip_vary on;即可自动加Vary: Accept-Encoding,无需手动add_header - 空
Origin(非跨域请求)会导致缓存分裂,可用map将其统一映射为"null",保持键结构稳定
按实际响应逻辑决定是否 Vary
Vary 不是越多越好,而是“只在后端真返回不同内容时才加”:
- 如果 API 对所有 Origin 都返回
Access-Control-Allow-Origin: *,就不该Vary: Origin——加了反而让每个源建独立缓存 - 如果后端根据
Accept-Language返回中文/英文 HTML,才需Vary: Accept-Language;若只是前端 JS 切语言,就不该加 - 图片服务支持 WebP 时,只有当同一 URL 真返回 JPEG 或 WebP 两种格式,才应
Vary: Accept
强制输出与透传控制
有些响应状态码(如 304、404)默认不走 add_header,容易漏掉 Vary:
- 加
always参数确保所有响应都带:add_header Vary "Origin" always; - 检查是否误启
proxy_ignore_headers Vary;,它会直接丢弃后端返回的Vary,导致缓存行为失控 - 若后端已返回正确
Vary,Nginx 默认透传;但为防遗漏,显式设置更稳妥











