この記事はディップ Advent Calendar 2024の16日目の投稿です。
背景
Amazon CloudFrontからクライアントに対して行うレスポンスについて調査するきっけは動作確認の際の挙動などが不明だったためになります。
コンテンツに対してアクセスした際、CloudFrontが導入されておりますと、レスポンスヘッダーに対してCloudFrontの挙動を確認するためのx-cache
ヘッダーが付与されますので、そちらに対して学んだことを記述出来ればと思います。
Amazon CloudFrontの概要
Amazon CloudFrontは、AWSが提供するグローバルなCDNサービスです。
CDNを利用すると、コンテンツ配信の高速化とオリジンの負荷を軽減できる利点があります!
例えばユーザからアクセスされたときは、近いCDNにキャッシュしているのでレスポンスが早くなり、CDNのキャッシュを返す場合はオリジンサーバへアクセスしないためオリジンサーバのCPUなどのリソースを温存出来るためです!
実際にどれぐらい早くなるかは、AWS公式のハンズオンから試してみることが可能なので是非試してみてください!
また、CloudFrontについて詳しくは、以下の公式ドキュメントを参照してください!
既存コンテンツのキャッシュ更新
大別して2通りあります。
- ファイル名にバージョン識別⼦を使⽤して更新する
- 同じ名前を使⽤してファイルを更新する
ファイル名にバージョン識別⼦を使⽤して更新する
以下の表のように更新前後でコンテンツのファイル名が違う場合、CloudFrontのキャッシュの挙動はどうなるのでしょうか?
更新前後 | コンテンツ |
---|---|
更新前 | img_v1.jpg |
更新後 | img_v2.jpg |
なんてことないのですが、更新の前後でコンテンツのファイル名が違う場合は、別々のキャッシュとして保存されます。
この方法は、明示的にキャッシュが更新を行えるという利点がありますが、呼び出し元の変更必要なのでアプリ改修などの工数がかかってしまう欠点もあります。
同じ名前を使⽤してファイルを更新する
以下の表のように更新前後でコンテンツのファイル名は同じだがファイルの内容が違うものの場合、CloudFrontのキャッシュの挙動はどうなるのでしょうか?
更新前後 | コンテンツ |
---|---|
更新前 | img_v1.jpg |
更新後 | img_v1.jpg |
コンテンツのメタ情報を使って別ファイルということを認識し、キャッシュの更新を行います。
コンテンツには多くのメタ情報 (Cookies, クエリ文字列, ヘッダー)が紐づいているため、コンテンツのファイル名が同じでもメタ情報を使って別ファイルだということを認識しています。
CloudFrontでファイル識別に使用されるメタ情報は、以下になります。
メタ情報 | 内容 |
---|---|
etag ヘッダー | コンテンツの特定のバージョンを示すもの |
last-modified ヘッダー | 最終更新日時を示すもの |
コンテンツのキャッシュの有効期限が切れると再度クライアントからCloudFrontにアクセスがあった際に、オリジンサーバに対してEtag
/Last Modifified
に変更があるかHTTPヘッダーの値( IF-Modified-Since
/ If-None-Match
)を用いて確認します。
このときもし、キャッシュしたコンテンツに変更がない場合は、IF-Modified-Since
/ If-None-Match
のレスポンスとEtag
/Last Modifified
の値に変更がなければ、クライアントに304(Not Modified)
とx-cache : RefleshHit from cloudfront
を返してキャッシュ期間を更新します。
以降は、またコンテンツのキャッシュが切れるまでCloudFront内のキャッシュを返し続けます。
また、キャッシュしたコンテンツに変更がある場合は、IF-Modified-Since
/ If-None-Match
のレスポンスとEtag
/Last Modifified
の値に変更があれば、クライアントに200(OK)
とx-cache : Miss from cloudfront
を返してコンテンツ内容とキャッシュ期間を更新をします。
以降は、またコンテンツのキャッシュが切れるまでCloudFront内のキャッシュを返し続けます。
キャッシュしたコンテンツに対する変更 | CloudFrontからクライアントへのHTTPレスポンス | CloudFrontからクライアントへのx-cache レスポンスヘッダー |
---|---|---|
変更がない | 304(Not Modified) |
x-cache : RefleshHit from cloudfront |
変更がある | 200(OK) |
x-cache : Miss from cloudfront |
CloudFrontからクライアントへのブラウザでキャッシュの挙動をx-cache
レスポンスヘッダーで確認することができます。
x-cache レスポンスヘッダー | 説明 |
---|---|
Hit from cloudfront | CloudFront にキャッシュがあったので、それを返した |
RefreshHit from cloudfront | CloudFront にキャッシュはあったが、有効期限が切れており、オリジンサーバに最新か確認した後に返した |
Miss From cloudfront | 現在 CloudFront にキャッシュが無い状態なので、オリジンサーバにコンテンツを取りに⾏って返した |
また合わせてCloudFrontのログからキャッシュの挙動を確認するための⽅法についても記載しておきます。
x-edge-result-type / x-edge-response-result-typeの値 | 説明 |
---|---|
HIT | CloudFront がキャッシュからクライアントにコンテンツを渡したことを⽰す |
RefreshHit | CloudFront のキャッシュにてコンテンツを検出したが、キャッシュの有効期限が切れていたため、オリジンサーバに問い合わせて、最新バージョンのコンテンツがあるかどうかを確認したことを⽰す |
Miss | CloudFront のキャッシュにあるコンテンツでリクエストに対応できなかったため、リクエストをオリジンサーバに転送して結果をクライアントに返したことを⽰す |
注意点としましては、有効期限を決める必要があり、有効期限を長くするとオリジンサーバへのリクエストが減らせますが、頻繁にコンテンツを更新する場合は有効期限を短くする必要があります。
また、指定したタイミングで一斉にキャッシュを更新したい場合は、キャッシュの無効化対応をする必要がありますのでご注意ください。
オリジンサーバが障害でダウンしてしまったとき
オリジンサーバから返される以下の HTTP 4xx および 5xx ステータスコードを常にキャッシュします。
ステータスコード | 意味 |
---|---|
404 | Not Found |
414 | Request-URI Too Large |
500 | Internal Server Error |
501 | Not Implemented |
502 | Bad Gateway |
503 | Service Unavailable |
504 | Gateway Time-out |
他にオリジンが Cache-Control max-age
または Cache-Control s-maxage
ヘッダーを返す場合、CloudFront は以下の HTTP 4xx ステータスコードのみをキャッシュします。
ステータスコード | 意味 |
---|---|
400 | Bad Request |
403 | Forbidden |
405 | Method Not Allowed |
412 | Precondition Failed |
415 | Unsupported Media Type |
キャッシュされたエラーはデフォルトで10秒間キャッシュします。これはカスタムエラーレスポンスの定義で変更が可能です。
また以下の二つで挙動が異なるなります。
- CloudFrontのキャッシュが有効期限切れの場合
- そもそもCloudFrontにキャッシュがない場合
CloudFrontのキャッシュが有効期限切れの場合
5xxエラーの場合、クライアントからCloudFrontに対してアクセスがあるとコンテンツキャッシュの有効期限が切れていることを確認したのち、オリジンサーバに対してEtag
/Last Modifified
に変更があるかHTTPヘッダーの値( IF-Modified-Since
/ If-None-Match
)を用いて確認します。
しかしながらオリジンサーバはダウンしているためCloudFrontからオリジンサーバへのキャッシュ更新確認のレスポンスが502 Bad Gateway
になります。
502 Bad Gateway
を受け取ったCloudFrontはクライアントに対してx-cache : RefleshHit from cloudfront
で有効期限切れのキャッシュを返します。
また4xxエラーの場合はオリジンサーバから受け取ったステータスコードをそのままクライアントへ返します。
そもそもCloudFronttにキャッシュがない場合
5xxエラーの場合、クライアントからCloudFrontに対してアクセスがあるとコンテンツをオリジンサーバに対して問い合わせます。
しかしながらオリジンサーバはダウンしているためCloudFrontからオリジンサーバへのキャッシュ更新確認のレスポンスが502 Bad Gateway
になります。
502 Bad Gateway
を受け取ったCloudFrontに502エラーをキャッシュし、クライアントに対してそのまま502 Bad Gateway
を返します。
キャッシュした502エラーはデフォルト10秒間キャッシュを保持しますが、カスタムエラーレスポンスでキャッシュ期間を変更することができます。
カスタムエラーレスポンスでエラーページを設定
もし、オリジンサーバが障害でダウンしている場合にはエラーページを表示させておきたい場合、カスタムエラーページを設定しておくと表示が可能になります。
オリジンサーバとは異なる場所にエラーページを配置しておき、カスタムエラーページの設定をするとオリジンサーバからのレスポンスが4xx,5xxだった時にエラーページの置いてあるオリジン(画像だとS3)に対してエラーページを要求しキャッシュをユーザへ表示するようになります。
終わりに
今回CloudFrontのレスポンスの挙動を調べてみてレスポンスヘッダーの意味合いなどに対して理解を深められました。
また調査の過程でTTLについても知見が多かったので後日まとめてみようと思いました。
参考