Amazon CloudFront のキャッシュ仕様についてあらためて調べてみた
2020-04-03Amazon CloudFront は AWS が提供している CDN サービスで、 AWS 環境で Web アプリケーションを運用する際に利用することが多いと思います。このブログの運用にも使用しているのですが、ふと CloudFront のキャッシュ仕様について気になったので、あらためて調べてみました。
気になったきっかけは先日書いたブログ記事です。
目次
前提
CloudFront の Web Distribution において、 オリジンに S3 を指定している場合 のキャッシュ仕様について自分なりにまとめたものになります。公式ドキュメント以上の内容はありません。
また、 RTMP Distribution または Web Distribution でカスタムオリジンを指定している場合は挙動が変わる部分もあるので、詳細は公式ドキュメントを参照してください。
ちなみに、RTMP Distribution は 2020/12/31 でサポートが終了するみたいです。
触れること
今回は、 Amazon CloudFront (以下、 CloudFront) のキャッシュ仕様について調べてみた内容をまとめます。具体的には、 Web Distribution の Behavior の設定画面で出てくる項目のうち、次の項目についてです。
- Cached HTTP Methods
- Cache Based on Selected Request Headers
- Object Caching
- Forward Cookies
- Query String Forwarding and Caching
設定画面では下のキャプチャ内で赤枠で囲った部分です。
各項目の概要
上であげた項目の詳細の前に、簡単にそれぞれの項目が何を設定する項目なのか、概要をおさらいします。
Cached HTTP Methods
キャッシュ対象とする HTTP メソッドを指定します。
Cache Based on Selected Request Headers
リクエストヘッダの情報をもとにキャッシュするかどうかを指定します。
Object Caching
キャッシュ時間を指定します。
Forward Cookies
Cookie をもとにキャッシュするかどうかを指定します。
Query String Forwarding and Caching
クエリパラメータをもとにキャッシュするかどうかを指定します。
各項目の詳細
では、各項目の指定内容と仕様についてまとめていきます。
Cached HTTP Methods
キャッシュ対象とする HTTP メソッドを指定します。デフォルトで GET
と HEAD
はキャッシュ対象になっており、対象から外すことはできません。
Allowed HTTP Methods の指定方法によって、選択できる HTTP メソッドが下記のように変わります。
「GET, HEAD」を指定した場合
デフォルトの GET
と HEAD
のみキャッシュ対象となります。
「GET, HEAD, OPTIONS」 または「GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE」を指定した場合
デフォルトの GET
と HEAD
に加えて OPTIONS
もキャッシュ対象にすることが可能です。
Cache Based on Selected Request Headers
CloudFront は、デフォルトではオリジンのオブジェクトをキャッシュする際にリクエストヘッダは考慮されません。なので、例えば下記のように custom-header
に別々の値を指定してリクエストしても、 どちらか一方のみがキャッシュされる ことになります。
GET /get HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: httpbin.org
User-Agent: HTTPie/2.0.0
custom-header: foo
GET /get HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: httpbin.org
User-Agent: HTTPie/2.0.0
custom-header: bar
Cache Based on Selected Request Headers の項目では、リクエストヘッダをもとにキャッシュするかどうかを、次の 3 つの方法でしていします。
None (Improves Cacheing)
オブジェクトをキャッシュする際に、リクエストヘッダは考慮されません。上であげた例の通り、特定のヘッダの値が異なっていても、どちらか (複数のパターンが有る場合はどれかひとつ) のオブジェクトをキャッシュします。
デフォルトではこの方法が指定されています。
Whitelist
明示的に指定したリクエストヘッダの値に基づいてオブジェクトをキャッシュします。たとえば、上の例で使用した custom-header
というヘッダをホワイトリストで指定した場合、 custom-header: foo
と custom-header: bar
は別々にキャッシュされます。
Behavior の設定画面ではこの方法を指定するとテキストエリアが表示されるので、キャッシュ対象としたいリクエストヘッダ名を改行で区切って指定します。
CloudFront はデフォルトでいくつかのリクエストヘッダをオリジンに転送しますが、キャッシュ対象となるのはホワイトリストで指定したヘッダのみです。また、ホワイトリストに指定できるヘッダの上限は、 10 となっています。この数を超えて指定したい場合は、クォータの引き上げリクエストをする必要があります。
All
すべてのリクエストヘッダをオリジンに転送します。その代わり、この設定をした場合 CloudFront は、 この Behavior で対象となるオブジェクトをキャッシュしない ようになります。
Object Caching
CloudFront がオリジンのオブジェクトをキャッシュし、再度オリジンにリクエストを転送するまでの時間 (キャッシュに保持する時間) を指定します。ここで指定した時間、キャッシュは CloudFront のエッジロケーションに保持され、オブジェクトはそこからビューアへ返却されます。
ただし頻繁にアクセスが無いオブジェクトに関しては、キャッシュ保持時間に達する前にエッジロケーションから削除される場合もあります。
デフォルトでは 24 時間 (86400 秒) 後にキャッシュの有効期限が切れるようになっていますが、次の 2 つの方法でキャッシュ時間を制御します。
Use Origin Cache Headers
オリジンのオブジェクトに指定されている Cache-Control: max-age
または Cache-Control: s-maxage
または Expires
ヘッダの値をもとにキャッシュ時間を制御します。これらのヘッダがオリジンのオブジェクトに存在しない場合は、デフォルトの 24 時間 が適用されます。
各ヘッダの指定方法の例は下記のようになります。
Cache-Control: max-age=3600
Cache-Control: s-maxage=3600
Expires: Thu, 30 Apr 2020 23:59:59 GMT
CloudFront では Cache-Control: max-age
と Cache-Control: s-maxage
を併用することができます。また、 Cache-Control: max-age
と Expires
を両方指定した場合、 CloudFront は Cache-Control: max-age
の値を使用します。 挙動については後述します。
Customize
デフォルトでは 24 時間となっているキャッシュ時間を、 最小 (Minimum TTL) 、 最大 (Maximum TTL) 、 デフォルト (Default TTL) の 3 つの値で指定します。各値が適用される条件については後述します。
キャッシュの保持時間の挙動
実際に CloudFront のエッジロケーションでキャッシュが保持される時間、およびブラウザでのキャッシュ保持時間は、オリジンのオブジェクトのヘッダ情報と、Minimum/Maximum/Default および CloudFront のデフォルト (24h = 86400sec) の条件によって変わります。具体的には下記の条件の組み合わせになります。
オリジン
Cache-Control: max-age
が存在するCache-Control: max-age
が存在しないCache-Control: max-age
およびCache-Control: s-maxage
が存在するExpires
が存在するCache-Control: no-cache
、no-store
、private
のいずれかが存在する
CloludFront
- Minimum TTL = 0 秒
- Minimum TTL > 0 秒
※表内では表記の都合上、 Minimum TTL、 Maximum TTL をそれぞれ MIN と MAX と書いてます
オリジン | Minimum TTL = 0 | Minimum TTL > 0 |
---|---|---|
Cache-Control: max-age あり |
CloudFront max-age と Maximum TTL の小さい方の値 ブラウザ max-age の値 |
CloudFront ・MIN < max-age < MAX の場合 max-age の値 ・ max-age < MIN の場合 Minimum TTL の値 ・ max-age > MAX の場合 Maximum TTL の値 ブラウザ max-age の値 |
Cache-Control: max-age なし |
CloudFront Default TTL の値 ブラウザ ブラウザによる |
CloudFront Default TTL または Min TTL のうち大きい方の値 ブラウザ ブラウザによる |
Cache-Control: max-age および Cache-Control: s-maxage あり |
CloudFront s-maxage と Maximum TTL の小さい方の値 ブラウザ max-age の値 |
CloudFront ・MIN < s-maxage < MAX の場合 s-maxage の値 ・ s-maxage < MIN の場合 Minimum TTL の値 ・ s-maxage > MAX の場合 Maximum TTL の値 ブラウザ max-age の値 |
Expires あり |
CloudFront Expires の日付と Maximum TTL に対応する日付の早い方の日付まで ブラウザ Expires の日付まで |
CloudFront ・MIN < Expires < MAX の場合 Expires の日付まで ・ Expires < MIN の場合 Minimum TTL に対応する日付まで ・ Expires > MAX の場合 Maximum TTL の値に対応する日付まで ブラウザ Expires の日付まで |
Cache-Control: no-cache 、 no-store 、 private のいずれかあり |
CloudFront ヘッダを優先 ブラウザ ヘッダを優先 |
CloudFront Minimum TTL の値 ブラウザ ヘッダを優先 |
より詳細な表については下記公式ドキュメントを参照してください。
Forward Cookies
CLoudFront では、デフォルトでキャッシュに Cookie が考慮されません。この項目ではオリジンに Cookie を転送し、 Cookie の値によってキャッシュをするかどうかを次の 3 つの方法で指定します。
None (Improves Caching)
Cookie をオリジンに転送せず、キャッシュに考慮しません。また、リクエストヘッダから Cookie
ヘッダを削除し、レスポンスヘッダから Set-Cookie
ヘッダを削除します。
Web Distribution ではオリジンによって Cookie を処理しないパターンがあり、その場合はこの方法を指定するべきです。今回の前提としている S3 は Cookie を処理しないため、この項目では None を指定します。
S3 の他、 Cookie を処理しないオリジンの場合に None 以外を指定するとパフォーマンスの低下に繋がります。
Whitelist
ホワイトリストで指定した Cookie のみオリジンに転送し、その値をもとにキャッシュを保持します。指定した Cookie 以外はオリジンへの転送時に削除されます。一方、指定していない Cookie がオリジンからのレスポンスに含まれていた場合は、その値も含めてビューアに返却します。
指定方法はリクエストヘッダの場合と同様で、改行区切りで指定します。
All
すべての Cookie をオリジンに転送し、その値をもとにキャッシュを保持します。キャッシュに考慮されるのはリクエスト時に含まれていた Cookie のみで、リクエストには含まれずオリジンからのレスポンスには含まれるような Cookie はキャッシュに考慮されません。
ビューアへのレスポンスには、リクエストとオリジンからのレスポンスの両方の Cookie がすべて返却されます。
Query String Forwarding and Caching
リクエスト URL に含まれる ?
以降の文字列で指定されたクエリパラメータをもとにキャッシュを保持するかを指定します。指定方法は次の 3 です。
None (Improves Caching)
クエリパラメータをオリジンに転送せず、キャッシュに考慮しません。つまり、下記のリクエストではすべてキャッシュされるのはどれか一つのみとなります。
- https://michimani.net/js/bundle.js
- https://michimani.net/js/bundle.js?query_param=value1
- https://michimani.net/js/bundle.js?query_param=value2
Foward all, cache based on whitelist
ホワイトリストで指定したパラメータのみオリジンに転送し、その値をもとにキャッシュを保持します。例えば上の例で使用した query_param
というパラメータをホワイトリストで指定した場合、上の 3 つは別々にキャッシュされます。一方で、指定していないパラメータはキャッシュに考慮されないため、下記のリクエストはすべて同一とみなされます。
- https://michimani.net/js/bundle.js
- https://michimani.net/js/bundle.js?query_param_2=value1
- https://michimani.net/js/bundle.js?query_param_2=value2
下記も同一となります。
- https://michimani.net/js/bundle.js?query_param=value1&query_param_2=value2_1
- https://michimani.net/js/bundle.js?query_param=value1&query_param_2=value2_2
Foward all, cache based on all
すべてのクエリパラメータをオリジンに転送し、その値をキャッシュに考慮します。
クエリパラメータによるキャッシュの注意点
クエリパラメータによるキャッシュを利用する場合に注意したいのが、 パラメータの順序 と パラメータの値の大文字/小文字 です。これらに注意しないと、オリジンへの不要なリクエストが発生し、パフォーマンスが低下する可能性があります。
パラメータの順序
例えば下記の 2 つのリクエストがあるとします。
- https://michimani.net/images/2020040220492101.jpg?width=1200&height=900&color=brack
- https://michimani.net/images/2020040220492101.jpg?height=900&color=black&width=1200
オリジンからすればどちらも width: 1200
, height: 900
, color: black
のパラメータですが、CloudFront ではこれらは別々のキャッシュとして保持されます。
パラメータの値の大文字/小文字
パラメータの順序と同様に、パラメータ名および値の大文字/小文字について注意が必要です。
- https://michimani.net/images/2020040220492101.jpg?color=brack
- https://michimani.net/images/2020040220492101.jpg?Color=brack
- https://michimani.net/images/2020040220492101.jpg?color=Brack
- https://michimani.net/images/2020040220492101.jpg?Color=Brack
もしオリジン側では大文字/小文字を区別していなかったとしても、 CloudFront では上の 4 つはすべて別々のキャッシュとして保存されます。
まとめ
Amazon CloudFront において、 Web Distribution で S3 をオリジンに指定した際のキャッシュの仕様についてあらためて調べてみた話でした。
これまでなんとなく指定していた項目 (特にキャッシュ保持時間) もあって、やっぱり公式ドキュメントをしっかり読むのは大事だなと思いました。逆に言えば、 AWS は公式ドキュメントが非常に充実していて読みやすいということが言えると思います。
今回これだけの内容をまとめるのに結構時間がかかりましたが、まだまだ触れられていない内容もたくさんあります。もう疲れたのでこれ以上は書きませんが、今後も公式ドキュメントをしっかり読む癖は続けていきたいと思います。
comments powered by Disqus