HTTP 的 Vary 头告诉缓存哪些请求头可能影响响应,这样缓存就不会把面向浏览器的 HTML 返回给请求 JSON 的 API 客户端。Cloudflare 引用了一项针对近 5 万个热门站点、超过 1.2 亿条响应的外部分析,发现近 3000 个站点在四个或更多字段上存在变化,有些在 10 个、23 个甚至 47 个字段上变化。Vary 本身是正确的,但如果照字面执行,可能让缓存几乎失去价值:三个字段各取十个值,就已经可能产生多达 1000 种变体;而像 Accept-Language 这样的请求头,即使顺序或格式不同,对源站而言也可能含义相同。

结果就是一个“完全正确却几乎永远冷”的缓存:字节完全相同的响应分散在许多几乎不会被复用的条目中,彼此驱逐,并把更多请求推回源站。现有的变通做法——完全绕过缓存、在 Worker 中复制内容协商逻辑,或像图片 Vary 这样的窄范围功能——要么放弃了缓存,要么重复了应用逻辑,要么只覆盖了一种情况。

现在,缓存规则允许源站继续声明 Vary 头,同时由一条规则设置按请求头决定:是将值归一化为一个小的等价集合,还是原样传递精确值,或是对不可预测的请求头绕过缓存。两个 Accept-Language 请求——en-US, fr;q=0.8 和 fr;q=0.8, en-GB——都偏好英语,在归一化模式下现在可以共享同一个缓存条目,而不是变成两个变体;而必须精确变化的请求头可以使用原样传递。该功能即日起在 Free 到 Enterprise 各套餐中可用。

把“哪些会变化”与“变化程度有多少才算数”分开

按质量值对 Accept 和 Accept-Language 排序,并裁剪到一组配置好的格式,可以把字节不同但语义相同的请求归并为一个条目。

按请求头而非全局地选择归一化、原样传递或绕过,使运维人员可以把 Cookie 视为无界(绕过),同时把 Accept-Language 视为一个小的封闭集合(归一化)。

把归一化后的请求头值转发给源站,而不仅仅用于缓存键,可以让源站的响应选择与它最终被存储为哪个缓存变体保持一致。

Vary: * 仍然始终绕过缓存,因为它可能表示 HTTP 消息之外的因素(如客户端 IP)决定了响应,而任何请求头级别的规则都无法安全地对此进行归一化。

当一种正确性机制膨胀成组合爆炸式的浪费时,找出你把“不同的字节”和“不同的含义”当成同一件事的地方,并为运维人员分别提供一个独立的调节旋钮。

Cloudflare 表示,正在评估已过期的 IETF Availability Hints 草案中的思路是否能让源站直接描述其支持的表示形式,从而减少手动配置缓存规则应归一化哪些格式和语言的工作量。该文章将当前的归一化、原样传递、绕过三分法定位为填补现有选项(完全绕过、自定义缓存键或基于 Worker 的协商逻辑)之间的空白,而非最终设计。

从这里,追溯依据

参考来源

  1. We just shipped support for the ugliest part of HTTP: Vary The Cloudflare Blog · blog.cloudflare.com ·