合理组合Cache-Control与Vary可实现多终端差异化缓存,避免缓存污染;需用map将User-Agent归类为有限设备类型,设X-Device-Type头并Vary它,proxy_cache_key中包含该变量,静态资源通常无需Vary,HTML/API需三者协同。

在Nginx中,合理组合 Cache-Control 与 Vary 响应头,能有效支持多终端(如PC、移动端、小程序)内容的差异化缓存分发,避免“缓存污染”——即一个终端缓存覆盖了另一个终端本该返回的内容。
理解 Vary 的核心作用
Vary 告诉缓存系统(包括浏览器、CDN、Nginx proxy_cache):该资源的响应可能因请求头中的某些字段而不同,缓存时需将这些字段值纳入缓存键(cache key)计算。常见用法是:
-
Vary: User-Agent—— 按设备类型区分缓存(但不推荐直接用,原因见下) -
Vary: Accept-Encoding—— 区分 gzip/br/未压缩版本(Nginx 默认已处理) -
Vary: X-Device-Type—— 更可控:由上游或Nginx根据规则注入自定义设备标识
避免直接 Vary: User-Agent 的陷阱
User-Agent 字符串极长且高度碎片化(同一机型多个UA变体),会导致缓存命中率骤降,甚至击穿缓存。正确做法是:
- 在Nginx中用
map指令将$http_user_agent归类为有限枚举值,例如:mobile/desktop/weapp - 设置自定义头如
X-Device-Type,再让Vary依赖它 - 示例配置片段:
map $http_user_agent $device_type {
~*"(iPhone|Android|Mobile)" "mobile";
~*"(MiniProgram|MicroMessenger)" "weapp";
default "desktop";
}
server {
add_header X-Device-Type $device_type;
add_header Vary X-Device-Type;
# 后续 proxy_cache_key 需包含 $device_type
}
Cache-Control 与缓存层级协同设计
Cache-Control 控制缓存行为,但需与 Vary 和缓存键对齐,否则策略失效:
- 对静态资源(JS/CSS/图片):设
Cache-Control: public, max-age=31536000,并确保Vary不影响其缓存键(通常无需Vary) - 对HTML或API响应:若按设备类型返回不同HTML,必须同时满足三点:
– 设置Vary: X-Device-Type
– 在proxy_cache_key中包含$device_type
– 设置合理的Cache-Control: public, max-age=3600(避免过期太久)
验证与调试关键点
上线前务必验证缓存是否真正按设备分离:
- 用
curl -I检查响应头是否含Vary: X-Device-Type和对应X-Device-Type值 - 对比不同UA请求的
X-Cache(或自定义缓存命中头)是否独立命中 - 检查Nginx
proxy_cache_key是否明确包含$device_type,例如:proxy_cache_key "$scheme$request_method$host$request_uri $device_type";










