【実務・中級編】 GCP Cloud CDNのネガティブキャッシュ(Negative Caching)の有効化とエラーレスポンス保持 – クラウドインフラと仮想化ネットワーク実践ガイド

なぜ「エラー」をキャッシュするのか?――GCP Cloud CDNで学ぶネガティブキャッシュの極意

こんにちは。現場で叩き上げのSREをしています。

クラウドインフラを運用していると、避けて通れないのが「オリジンへの負荷」です。特に、存在しないリソースへの執拗なアクセスや、一時的な障害時に発生するエラーレスポンスが、バックエンドのデータベースやアプリケーションサーバーを直撃し、二次障害を引き起こす光景を何度も見てきました。

そんな時、我々エンジニアの強力な武器になるのが「ネガティブキャッシュ(Negative Caching)」です。今日は、GCP Cloud CDNにおけるこの機能を深掘りし、実務でどのように活用し、何を注意すべきか、現場の視点で解説します。

—

1. ネガティブキャッシュが解決する「負の連鎖」

通常、CDNは「成功したレスポンス(200 OKなど)」をキャッシュしますが、ネガティブキャッシュは「失敗したレスポンス(404 Not Found や 502 Bad Gateway など)」をあえて一定時間保持します。

なぜこれが必要か? 例えば、攻撃者や誤設定されたクライアントが、存在しないURL(/non-existent-resource)を毎秒数万回リクエストしてきたとします。もしネガティブキャッシュがない場合、そのリクエストはすべてオリジンに到達し、オリジンの CPU や DB のコネクションを食いつぶします。

ネガティブキャッシュを有効にすることで、最初のエラーレスポンスをエッジサーバーが「覚えて」おき、次回以降のリクエストはオリジンに飛ばさずエッジで即座に遮断(あるいはエラーを返却)できるのです。

—

2. 通信フロー:パケットはどこで止まるのか

ネガティブキャッシュが有効な場合、通信のシーケンスは以下のようになります。

1. クライアントがリクエストを送出。
2. エッジサーバーがキャッシュを検索し、ヒットしなければオリジンへ転送。
3. オリジンが 404 Not Found を返却。
4. エッジサーバーがそのステータスと Cache-Control ヘッダーを解析し、一定期間(TTL)キャッシュとして保存。
5. 次回以降のリクエストに対しては、オリジンを叩かずエッジが 404 を即座に応答。

この「オリジンを叩かない」という一点が、大規模トラフィック下では命綱になります。

—

3. GCP Cloud CDNでの設定とパラメータ

GCPでこれを制御するのは、主にバックエンドサービスの negativeCachingPolicy という設定です。

設定の勘所

  • code: キャッシュ対象とするHTTPステータスコード(404, 502, 503, 504など)。
  • ttl: エラーをキャッシュする秒数。短すぎると負荷軽減にならず、長すぎると復旧後の追従が遅れます。

以下は、gcloud コマンドで設定を適用する例です。

# 対象のバックエンドサービスに対してネガティブキャッシュポリシーを適用
gcloud compute backend-services update [YOUR_BACKEND_SERVICE_NAME] \
    --global \
    --negative-caching \
    --negative-caching-policy="404=300,502=60" 
    # 404は300秒(5分)、502は60秒キャッシュする設定

—

4. 実務上の注意点:キャッシュの罠

ネガティブキャッシュは諸刃の剣です。以下の点には細心の注意を払ってください。

① 502/503/504 の扱い

404 をキャッシュするのは安全ですが、502 Bad Gateway や 503 Service Unavailable を長時間キャッシュするのは危険です。オリジンが復旧した瞬間に、エッジのキャッシュが消えるまで「ずっとエラーが続く」という悲劇を招きます。これらは短めの TTL に設定するのが鉄則です。

② ヘッダーの確認

Cloud CDN がエラーをキャッシュするかどうかは、オリジンが返す Cache-Control ヘッダーにも依存します。もしオリジンが Cache-Control: private や no-store を返していれば、設定に関わらずキャッシュされません。

以下は、オリジン側で適切に制御するためのPython(Flask)のサンプルです。

from flask import Flask, make_response

app = Flask(__name__)

@app.route('/test-error')
def error_route():
    # 意図的にエラーを返しつつ、CDNにキャッシュさせるためのヘッダーを付与
    response = make_response("Not Found", 404)
    response.headers['Cache-Control'] = 'public, max-age=300'
    return response

—

5. デバッグのTips:正しくキャッシュされているか?

「設定したはずなのに効いていない」という時、私は必ず curl で Via ヘッダーと Age ヘッダーを確認します。

# -Iでヘッダーのみ取得
curl -I https://your-site.com/non-existent-resource

期待通りの挙動であれば、レスポンスヘッダーに以下が含まれます。

  • X-Cache: HIT (キャッシュから返却されている)
  • Age: [秒数] (キャッシュされてからの経過時間)

もし X-Cache: MISS が続くようなら、オリジンの Cache-Control ヘッダーが邪魔をしていないか、あるいは GCP のコンソール上で「キャッシュキーの構成」が意図した通りになっているかを確認してください。

—

まとめ

ネガティブキャッシュは、単なる「エラーの記憶」ではなく、「オリジンを守るための防波堤」です。

1. 404 は長めにキャッシュしても安全(リソースが復活する頻度は低いため)。
2. 5xx系 は慎重に。復旧を阻害しないよう極短時間に設定。
3. ヘッダーの確認 を怠らない。

この機能を使いこなせれば、トラフィックのスパイクが起きても、肩の力を抜いてコーヒーを飲んでいる余裕が生まれます。皆さんのインフラが、より堅牢なものになることを願っています。

それでは、また現場でお会いしましょう。

コメント

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