HTTPのVaryヘッダーは、どのリクエストヘッダーがレスポンスに影響し得るかをキャッシュに伝えるもので、これによりキャッシュがブラウザ向けのHTMLをJSONを求めるAPIクライアントに返してしまうことを防ぐ。Cloudflareは、約5万の主要サイトにわたる1億2000万件超のレスポンスを分析した外部調査を引用しており、そこでは約3,000件が4つ以上のフィールドで変動し、中には10、23、さらには47のフィールドで変動するものもあった。Varyは正しい仕組みだが、文字通りに解釈するとキャッシュがほぼ無価値になり得る。3つのフィールドにまたがる10個の値だけで最大1,000のバリアントが生まれ、Accept-Languageのようなヘッダーはオリジンにとって同じ意味であっても順序や書式が異なり得る。

その結果、キャッシュは「完全に正しく、かつほぼ恒久的にコールド」な状態になる。バイト単位で同一のレスポンスが、ほとんど再利用されない多数のエントリに分散し、互いを追い出し、より多くのリクエストをオリジンに押し戻す。既存の回避策、すなわちキャッシュを完全にバイパスする、Worker内でネゴシエーションロジックを複製する、あるいは画像向けのVaryのような限定的な機能は、いずれもキャッシュを諦めるか、アプリケーションロジックを複製するか、1つのケースしかカバーしないかのいずれかであった。

Cache Rulesは現在、オリジンがVaryヘッダーを宣言し続ける一方で、ルール設定によりヘッダーごとに、値を小さな等価集合に正規化するか、正確な値をそのまま通すか、予測不能なヘッダーについてはキャッシュをバイパスするかを決められるようにする。英語を優先する2つのAccept-Languageリクエスト、en-US, fr;q=0.8 と fr;q=0.8, en-GB は、normalizeの下では2つのバリアントになる代わりに1つのキャッシュエントリを共有できる。一方、正確に変動させる必要があるヘッダーはpassthroughを使える。これは本日、FreeからEnterpriseまでのプランで利用可能である。

何が変動するかと、どれだけの変動が意味を持つかを分離する

AcceptとAccept-Languageを品質値でソートし、設定された書式の集合に絞り込むことで正規化すると、バイト単位では異なるが意味的には同一のリクエストが1つのエントリに集約される。

normalize/passthrough/bypassの選択をグローバルではなくヘッダーごとに行うことで、オペレーターはCookieを無制限(bypass)として扱いつつ、Accept-Languageを小さな閉じた集合(normalize)として扱える。

正規化されたヘッダー値をキャッシュキーに使うだけでなくオリジンに転送することで、オリジンのレスポンス選択が、どのキャッシュバリアントとして保存されるかと整合し続ける。

Vary: * は常にキャッシュをバイパスする。クライアントIPのようにHTTPメッセージの外側の要因がレスポンスを左右したことを示し得るためであり、ヘッダーレベルのルールでは安全に正規化できない。

正しさのための仕組みが組み合わせ爆発的な無駄に膨れ上がるとき、「異なるバイト」と「異なる意味」を同じものとして扱っている箇所を見つけ、オペレーターにそれぞれ別個の調整手段を与えよ。

Cloudflareは、失効したIETFのAvailability Hintsドラフトのアイデアにより、オリジンがサポートする表現を直接記述できるようにし、Cache Ruleがどの書式と言語を正規化すべきかを設定する手作業を減らせるかどうかを検討していると述べている。この投稿は、現在のnormalize/passthrough/bypassの分割を、最終的な設計としてではなく、既存の選択肢(完全なバイパス、カスタムキャッシュキー、Workerベースのネゴシエーションロジック)の間の隙間を埋めるものとして位置づけている。

出典をたどる

出典

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