【テクニカル・上級編】 GCP Cloud CDNのキャッシュキー(Cache Key)の構成要素とカスタマイズ仕様 – クラウドインフラと仮想化ネットワーク実践ガイド

GCP Cloud CDNの深淵:キャッシュキーという「指紋」を制御し、エッジのポテンシャルを極限まで引き出す

こんにちは。インフラの深淵を覗き込み、パケットの呼吸を感じることを日課としているSREです。

皆さんはGCPのCloud CDNを単なる「キャッシュサーバー」と呼んでいませんか?もしそうなら、それはフェラーリで近所のコンビニに買い物に行くようなものです。Cloud CDNはGoogleの巨大なグローバルエッジネットワークに直結した、レイヤ7の強力なトラフィック最適化エンジンです。

その心臓部である「キャッシュキー(Cache Key)」を正しく理解し、チューニングすることは、バックエンドサーバーの負荷を劇的に下げ、ユーザー体験をミリ秒単位で向上させるための最重要課題です。今日は、このキャッシュキーの内部挙動を解剖していきましょう。

—

キャッシュキーの正体:パケットが「同一」と見なされる瞬間

Cloud CDNにおけるキャッシュキーとは、簡単に言えば「あるリクエストに対して、どのキャッシュ済みオブジェクトを返すか」を決定するための識別子です。

デフォルトでは、Cloud CDNは以下の要素を組み合わせてキャッシュキーを生成します。

  • Protocol (HTTP or HTTPS)
  • Host (リクエスト先のホスト名)
  • Path (URIパス)

ここでインフラエンジニアとして意識したいのは、「何がキーに含まれ、何が除外されているか」です。例えば、クエリパラメータや特定のHTTPヘッダーをキーに含めない設定のままにしておくと、本来は個別のコンテンツを返すはずのリクエストが、誤ってキャッシュされた共有コンテンツを返してしまう、という致命的な不整合を招きます。

クエリパラメータの制御:カオスを秩序に変える

動的なWebアプリでは、同じパスに対して無数のクエリパラメータが付与されます。例えば、?utm_source=... のような解析用パラメータをすべてキャッシュキーに含めてしまうと、キャッシュヒット率は壊滅的に低下します。

これを制御するのが queryParameters の設定です。特定のパラメータのみをキーに含めることで、無駄なキャッシュ生成を抑制します。

# 特定のクエリパラメータのみをキャッシュキーに含める設定例 (gcloud CLI)
# この設定により、'version' と 'lang' 以外のパラメータはキャッシュキーから除外される
gcloud compute backend-services update [BACKEND_SERVICE_NAME] \
    --global \
    --cache-key-include-query-parameters=version,lang

—

HTTPヘッダーとVaryの向こう側:トランスポート層への配慮

キャッシュの粒度を細かくしすぎると「キャッシュの断片化」が起き、広げすぎると「セキュリティやUXの汚染」が起きます。ここで重要になるのが Vary ヘッダーと、Cloud CDNの includeCustomizedHeaders です。

特に、Accept-Encoding や Authorization ヘッダーを扱う場合、注意が必要です。例えば、圧縮アルゴリズム(BrotliやGzip)の違いを意識する場合、Cloud CDNは自動的に Vary: Accept-Encoding を考慮しますが、カスタムヘッダーでデバイスタイプや国コードを識別している場合は、明示的な設定が必要です。

警告:ヘッダーの選択が招く脆弱性

includeCustomizedHeaders を使用して Cookie ヘッダーなどをキーに含めるケースを見かけますが、これには細心の注意が必要です。もしセッションIDのような高機密な情報をキャッシュキーに含めてしまうと、CDNノードがそのIDを基にキャッシュを保持・共有することになり、最悪の場合、ユーザー間でキャッシュが漏洩するリスクがあります。

教訓: キャッシュキーに含めるヘッダーは、必ず「公開情報」に限定すること。

—

パフォーマンスの最適化:TLSハンドシェイクとRTTの削減

キャッシュキーの最適化は、実はTCP/TLSのオーバーヘッドとも密接に関係しています。

キャッシュキーが効率的にヒットするということは、ユーザーのブラウザからのリクエストが、地理的に最も近いGoogleのPoP(Point of Presence)で完結することを意味します。これにより、以下のメリットが享受できます。

1. TLS False Start & 0-RTT: キャッシュヒットすれば、バックエンドへのRTT(往復時間)を完全に排除できます。
2. TCPバッファチューニング: Googleのインフラは、パケットロスがわずかでも発生した際のTCPウィンドウサイズ調整が極めて高度です。キャッシュをエッジに置くことで、ユーザーとの最も「過酷な」ラストワンマイルの接続のみを最適化すればよくなります。

HTTP/2とヘッダー圧縮 (HPACK) の恩恵

キャッシュキーを最適化し、レスポンスヘッダーを整理することで、HPACKによるヘッダー圧縮の効率が向上します。重複するヘッダーをキャッシュキーから排除できれば、パケットサイズが小さくなり、輻輳制御アルゴリズム(BBRなど)との相乗効果で、さらなる低レイテンシが実現可能です。

—

現場で使える設計指針

最後に、実戦で私が推奨するキャッシュキー設計のベストプラクティスを共有します。

  • 正規化を徹底せよ: クエリパラメータの順序をバックエンド側でソートし、CDN側でもパラメータの包含を最小限にする。
  • キャッシュキーの「不変性」を保つ: APIのバージョンアップ時にはパスに含める(例: /v1/api -> /v2/api)。キャッシュのパージ(無効化)を頻繁に行うのは、Googleの巨大なエッジネットワークにとって負荷が高い。
  • デバッグには X-Cache-Status を使え: CDNが HIT しているのか MISS しているのか、その理由は何かを常に監視する。
# キャッシュキーのデバッグ用リクエスト例 (Python/Requests)
import requests

url = "https://your-domain.com/api/data"
headers = {"Cache-Control": "no-cache"} # CDNのキャッシュを無視して検証する場合

response = requests.get(url, headers=headers)
# レスポンスヘッダーの 'X-Cache' を確認する
print(response.headers.get('X-Cache')) 
# HIT, MISS, REVALIDATED などのステータスを確認し、キーが正しく設計されているかを検証

キャッシュキーの設計は、パケットの旅路をデザインすることと同義です。どこでデータを止めるか、どこでユーザーに届けるか。この細かな制御が、大規模トラフィックを捌くインフラの「品格」を決めます。

皆さんのアーキテクチャが、今日も安定して高速であることを祈っています。

コメント

タイトルとURLをコピーしました