我们刚刚上线了对 HTTP 中最丑陋部分的支持:Vary
内容提要
Cloudflare 在 Cache Rules 中新增 Vary 支持,以解决 HTTP Vary 头导致的缓存碎片化问题。源站可通过 Vary 声明影响响应的请求头,用户可选择三种处理方式:normalize 归一化 Accept、Accept-Language 等头,使等价请求共享缓存;passthrough 保留原始值精确匹配;bypass 对 Cookie、User-Agent 等高基数头跳过缓存。该功能已在所有套餐上线。
延伸解读
Vary 的核心矛盾:正确性与缓存效率
Vary 头能确保缓存不返回错误响应,但原始值匹配会导致缓存碎片化。例如,Accept-Language 的细微差异可能产生大量变体,即使响应内容相同。Cloudflare 的解决方案让用户通过 Cache Rules 决定如何处理每个头,在正确性和效率之间取得平衡。
三种处理方式:normalize、passthrough 与 bypass
normalize 对 Accept、Accept-Language 等头进行归一化,使等价请求共享缓存;passthrough 保留原始值精确匹配,适用于值受控且影响响应的头;bypass 对 Cookie、User-Agent 等高基数头跳过缓存。用户可根据头特性选择,默认推荐 normalize。
配置注意事项与最佳实践
源站必须为所有可能变化的可缓存响应一致地返回 Vary 头,包括错误响应。更改 Vary 配置不会自动清除旧缓存,需手动清除或等待过期。建议从 normalize 开始,对个性化头使用 bypass,并测试 CF-Cache-Status 确保缓存行为符合预期。
与自定义缓存键的对比
自定义缓存键会为规则覆盖的所有响应添加维度,无论源站是否使用。Vary 是响应驱动的,更灵活。当请求属性始终定义资源时用自定义缓存键;当源站声明一组请求字段时用 Vary。避免同一头同时用于两者,除非经过测试。
Q&A
Cloudflare 在 Cache Rules 中新增的 Vary 支持是什么?
Cloudflare 在 Cache Rules 中新增了对 HTTP Vary 头的支持,允许源站通过 Vary 声明影响响应的请求头,用户可选择三种处理方式:normalize、passthrough 或 bypass,以平衡缓存正确性和效率。该功能已在所有套餐上线。
HTTP Vary 头为什么会导致缓存碎片化?
Vary 头告诉缓存哪些请求头可能影响响应,但缓存无法判断不同头值是否真的需要不同响应。例如,Accept-Language 的不同顺序或标签可能映射到同一响应,但缓存会将其视为不同变体,导致大量几乎相同的缓存条目,降低缓存命中率并增加回源请求。
Cloudflare 的 Vary 支持提供了哪三种处理方式?分别适用于什么场景?
三种方式:normalize(归一化请求头,使等价请求共享缓存,推荐用于协商头如 Accept、Accept-Language);passthrough(使用原始头值精确匹配,适用于值受控且精确值影响响应的头);bypass(不缓存响应,适用于个性化、高基数或不可预测的头如 Cookie、User-Agent)。
如何通过 Cloudflare 仪表板或 API 配置 Vary 设置?
在仪表板中,进入 Caching > Cache Rules,创建或编辑规则,使响应可缓存,并添加 Vary 设置。设置默认行为,然后添加源站可能命名的头。也可通过 Rulesets API 在 http_request_cache_settings 阶段配置,提供 JSON 规则,指定 default 动作和每个头的动作。
normalize 动作如何归一化 Accept-Language 头?
normalize 会将 Accept-Language 值转为小写,按质量值降序排序(质量值相同按字母顺序),然后去除非零质量值的参数,并可能丢失 q=0。例如,en-US, fr;q=0.8 和 fr;q=0.8, en-GB 都可能归一化为 en,fr,从而共享缓存。
使用 Vary 时,源站需要承担什么责任?
源站必须为每个可能因请求字段而不同的可缓存响应一致地返回适当的 Vary 头,包括错误和回退响应。如果某个响应遗漏了 Vary,Cloudflare 可能会在不具备必要差异的情况下缓存该响应,导致错误内容被提供给后续请求。
Vary 和自定义缓存键有什么区别?
自定义缓存键将配置的维度添加到规则覆盖的每个响应中,无论源站是否使用它们。Vary 是响应驱动的,源站声明可能影响响应的请求字段,缓存据此处理。当请求属性始终定义资源时使用自定义缓存键;当源站在可缓存响应中声明相同的请求字段集时使用 Vary。避免将同一头同时放入两者,除非经过测试。