AWS
CloudFront

CloudFrontにおけるオリジンからのHTTP 5xxステータスコードのキャッシュ挙動

好きなAWSサービスはCloudFrontのコマコウです。
(本記事は、2017年12月20日時点のCloudFrontの仕様です。)

要点

  • CloudFrontはオリジンからのHTTP 5xxステータスコードを処理する際に、エッジロケーションのオブジェクト有無で挙動が異なる
  • キャッシュの有効期限が切れても、エッジロケーションはオブジェクトを保持し続けることはある
  • エッジロケーションにオブジェクトが無い場合:CloudFrontのカスタムエラーページ設定に従う
  • エッジロケーションにオブジェクトが有る場合:エッジロケーションのオブジェクトをレスポンスし続ける

背景

CloudFrontがオリジンからのHTTP 5xxステータスコード処理する際に、エッジロケーションに保持していたオブジェクトをビューワーにHTTP 200ステータスコードで応答し続けると問題があるシステムはあります。例えば、動的サイト・APIサービスでCloudFrontを利用している構成は注意が必要です。

環境

今回は、LAMP環境で、RDS/EC2(WEBサーバ)/ELB/CloudFrontを利用した環境を例とします。

CloudFrontの挙動

エッジロケーションにオブジェクトが無い場合

  1. ビューワーがリクエストする。
  2. エッジロケーションがオリジンにリクエストをする。
  3. オリジンが5xxエラーをエッジロケーションにレスポンスする。
  4. CloudFrontのカスタムエラーページの設定に従い、ビューワーにレスポンスする。 カスタムエラーページが未設定(デフォルト)の場合、5xxステータスコードをビューワーにレスポンスする。5分間に渡り、エッジロケーションは 5xxステータスコードをキャッシュする。 figure-1.png

エッジロケーションにオブジェクトが有る場合

  1. ビューワーがリクエストする
  2. オブジェクトの有効期限が切れてない場合は、エッジロケーションがオブジェクトをビューワーにレスポンスする。キャッシュの有効期限が切れている場合は、オリジン(ELB・WEBサーバ)にリクエストする
  3. オリジンが5xxエラーをエッジロケーションにレスポンスする
  4. カスタムエラーページのエラーキャッシュ最小 TTL の期間(デフォルトで5分)、エッジロケーションはビューワーに対して、オブジェクトの有効期限が切れていても、エッジロケーションに保持しているオブジェクトをレスポンスし続ける。エラーキャッシュ最小TTLを経過後のリクエストは、再度オリジンにリクエストを行う。
  5. 再度オリジンにリクエストされたオブジェクトが、5xxステータスコードをレスポンスすると、エッジロケーションに保持しているオブジェクトをレスポンスする。
  6. 1~5を繰り返えします。ビューワーにはエッジロケーションからオブジェクトが200ステータスコードでレスポンスされますので、表面上は正常に動作しているようにみえます。 figure-2.png

対策案

CloudFrontが、オリジンからの5xxステータスコードのレスポンスを、ビューワに 200ステータスコードでレスポンスさせない対策について検討しました。各環境によって、最善な方法は異なると思われます。(無作為にインバリデーションを行うと、エッジロケーションから、よしなに200ステータスコードでレスポンスされていたオブジェクトが、5xxステータスコードでレスポンスされますので、サービスダウンする可能性があります。)

  1. デプロイ時にCloudFrontのインバリデーション
    基本的な処理ですが、デプロイ後にインバリデーションを行い、エッジロケーションに保持しているオブジェクトをクリアにする。

  2. オリジン(ELB/WEBサーバ)の5xxエラーを監視モニタリング
    オリジンでHTTP 5xxステータスコードを検知したら、CloudFrontから応答しているレスポンスの確認を行う。5xxステータスコード対策後に、インバリデーションを行う。5xxステータスコードが頻繁に出ないようにエラーハンドリングしておこうね...

3. Lambda@Edgeを利用して、オリジンからHTTP 5xxステータスコードを応答したレスポンスに対して処理を加える。
こちらの対策は、発想段階なので、2017年度の冬休みの宿題とします。
※追記
(2017年12月21日時点)
Lambdaのドキュメントによると、 CloudFront オリジンレスポンスはオリジンが 400 以上の HTTP ステータスコードを返した場合に発火しない とのことです。
Lambda 関数をトリガーできる CloudFront イベント
http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-cloudfront-trigger-events.html

参考

上記の挙動は、公式ドキュメントに詳細に記載されております。
CloudFront がオリジンからの HTTP 4xx および 5xx ステータスコードを処理してキャッシュに保持する方法
http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/HTTPStatusCodes.html