GCP Cloud CDNの「キャッシュキー」を制する者は、Webパフォーマンスを制する。
現場でSREをしていると、「CDNを導入したのにキャッシュヒット率が上がらない」「特定のユーザーだけ古いコンテンツが見えている」という相談をよく受けます。その原因のほとんどは、キャッシュキー(Cache Key)の設計ミスです。
Cloud CDNは単なる「リクエストをキャッシュする箱」ではありません。リクエストのどの要素を「識別子」として採用するかを正しく制御できていないと、キャッシュの効率はガタ落ちし、オリジンサーバーへ無駄なトラフィックが流れ込みます。
今回は、Cloud CDNのキャッシュキーの仕組みと、実務でハマりやすいポイントを深く掘り下げて解説します。
—
そもそも「キャッシュキー」とは何か?
キャッシュキーとは、Cloud CDNが「このリクエストは、以前取得したあのレスポンスと同じものか?」を判定するための「指紋」のようなものです。
デフォルトでは、Cloud CDNは以下の要素を組み合わせてこの指紋を生成します。
1. プロトコル: http か https か。
2. ホスト名: リクエスト先のドメイン。
3. パス: /api/v1/resource のようなパス部分。
しかし、現代のAPI設計ではこれだけでは不十分です。クエリパラメータや特定のHTTPヘッダーがレスポンスの内容を左右することが多いため、これらをキャッシュキーに含める(あるいは除外する)カスタマイズが必要になります。
—
キャッシュキーのカスタマイズ:4つの主要構成要素
GCPでは、Backend Serviceの定義において、CacheKeyPolicyを調整することで詳細な制御が可能です。
1. クエリパラメータの制御
最も頻繁に調整するのが queryStringWhitelist(許可リスト)または queryStringBlacklist(拒否リスト)です。例えば、utm_sourceのようなトラッキング用パラメータはキャッシュキーから除外しないと、同じページなのにパラメータが違うだけで別キャッシュ扱いになり、キャッシュヒット率が壊滅します。
2. HTTPヘッダーの取り扱い
includeHttpHeaders を使うことで、特定のヘッダーをキーに含められます。例えば、モバイルとPCでレスポンスを出し分ける場合に User-Agent を含めるといったケースが考えられますが、これは慎重に扱うべきです。 User-Agent は種類が多すぎて「キャッシュの細分化(Cache Fragmentation)」を招き、ヒット率を著しく低下させるからです。
3. プロトコル(HTTP/HTTPS)の含めるべきか?
includeProtocol を有効にすると、同じURLでもプロトコルが違えば別キャッシュになります。基本的には true で運用しますが、HTTPからHTTPSへ強制リダイレクトしている環境であれば、キャッシュ層で分ける必要がないこともあります。
4. ホスト名の分離
includeHost を有効にすると、api.example.com と cdn.example.com でパスが同じでも別々にキャッシュされます。マルチテナント環境では非常に重要です。
—
実践:Terraformでのキャッシュキー最適化設定
現場での運用を考えると、コンソールでのポチポチ設定は推奨しません。Terraformでの定義例を見てみましょう。
resource "google_compute_backend_service" "api_backend" {
name = "api-backend"
cdn_policy {
cache_key_policy {
# 1. プロトコルはキャッシュキーに含める(推奨)
include_protocol = true
# 2. ホスト名は含める(マルチドメイン対応)
include_host = true
# 3. クエリパラメータは「必要なものだけ」をホワイトリスト化する
# これにより、不要なパラメータ(utm_系など)によるキャッシュ汚染を防ぐ
query_string_whitelist = ["id", "version", "region"]
# 4. 特定のカスタムヘッダーをキーに含める例
# APIのバージョン制御をヘッダーで行っている場合
include_http_headers = ["X-API-Version"]
}
}
}
—
トラブルシューティング:キャッシュが効かない時のデバッグ手順
キャッシュキーの設計が正しいか確認するには、実際にレスポンスヘッダーを覗くのが一番の近道です。curlコマンドを使って、CDNからのレスポンスを確認しましょう。
# -I でヘッダーのみを取得
# -H で必要に応じて検証用ヘッダーを追加
curl -I -H "X-API-Version: v1" "https://api.example.com/data?id=123&utm_source=google"
この際、注目すべきは以下のヘッダーです。
Via:1.1 googleとあればCloud CDNを通過しています。Age: キャッシュに滞在している秒数。0の場合はミスです。X-Cache:HITかMISSか。MISSが続く場合は、キャッシュキーがリクエストごとに変わっていないか疑ってください。
SREの教訓:パラメータの順序に注意
意外と見落としがちなのが、クエリパラメータの順序です。
Cloud CDNの queryStringWhitelist は、パラメータをキーに含める際、通常は「指定されたパラメータのみ」を識別子として使います。しかし、パラメータの「順序」がバラバラ(?a=1&b=2 と ?b=2&a=1)の場合、CDNの設定によっては別キャッシュとして認識されることがあります。
これを防ぐには、アプリケーション側でURL生成時にパラメータを辞書順にソートしておくのが、現場レベルでのベストプラクティスです。
—
まとめ:設計の哲学
キャッシュキーの設定において最も重要なのは、「何を変数として扱うか」というビジネスロジックの理解です。
- ヒット率を稼ぎたいなら: キーを可能な限り抽象化(固定化)する。
- 正確性を担保したいなら: キーに情報を詰め込む。
このトレードオフを理解し、Terraform等のコードで構成管理を行うことが、大規模Webサービスを運用するSREの第一歩です。次のデプロイでは、一度 CacheKeyPolicy を見直してみてはいかがでしょうか。きっと、オリジンサーバーのCPU負荷が劇的に下がるはずです。
コメント