CloudFrontのコンテンツの無圧縮、圧縮(BrotliとGzip)のリクエストを混在させた場合の挙動を確認してみた

2021.12.19

いわさです。

CloudFrontにはコンテンツを圧縮して配信する機能が備わっています。
以下の記事ではBrotliの設定方法や圧縮されていることを確認しています。

CloudFront側では本日時点でGzipとBrotliの2つの圧縮形式がサポートされていますが、一方でブラウザ毎のコンテンツ圧縮形式のサポート状況は異なっています。 CDN側でそのあたりをどのように吸収しているのか、CloudFrontを使って挙動とキャッシュ動作を確認してみました。
※各ブラウザで何がサポートされているのかについてはこの記事では触れません。

圧縮設定

CloudFront側でコンテンツ圧縮を有効化するには2つの設定が必要です。

  1. キャッシュビヘイビアでの「オブジェクトを自動的に圧縮」を有効化します。
  2. キャッシュポリシーの圧縮サポートを有効化します。

デフォルトのキャッシュポリシーであればCachingOptimizedが圧縮サポートの有効化がされています。
圧縮サポートはGzip、Brotliそれぞれで有効化が可能です。

圧縮の確認

オリジン設定されたS3バケットに適当なHTMLファイルをコンテンツアップロードし確認してみます。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=1000, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    ああああああああ
       ...
    ああああああ
</body>
</html>

CloudFrontでは、サイズが 1,000~10,000,000 バイトのオブジェクトを圧縮する仕様なので、その範囲内のファイルサイズであることを確認します。
また、圧縮するかどうかのファイルタイプもContent-Typeヘッダーを使って判断されます。

CloudFront が圧縮するファイルタイプ

クライアント毎にレスポンスを圧縮するか判断する仕組み

CloudFrontではリクエストのAccept-Encodinggzip, br, またはその両方が含まれていることによって圧縮を行います。
例えば、圧縮設定を有効にしたInternet Explorer 11だとgzipのみ送信されbrはサポートされていないので送信されません。
また、ChromeやFiregfoxを使った場合でもHTTPS利用時のみgzip,brを送付するなどブラウザによって対応状況や挙動は異なっています。

本日はcurlを使ってAccept-Encodingヘッダーを指定しレスポンスヘッダーを確認してみます。

無圧縮リクエスト

ここではContent-Encodingを確認しレスポンスが圧縮されているかを判断します。
curlのデフォルトではAccept-Encodingヘッダーは付与されないので、圧縮されません。

iwasa.takahito@hoge 20211219cloudfront % curl -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html   
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 105555
Connection: keep-alive
Date: Sat, 18 Dec 2021 23:26:25 GMT
Last-Modified: Sat, 18 Dec 2021 23:20:30 GMT
ETag: "eac7a9e486d059b18d5d841a740c9aa8"
Accept-Ranges: bytes
Server: AmazonS3
Vary: Accept-Encoding
X-Cache: Hit from cloudfront
Via: 1.1 04c2f7c6be96060d3defd0bb02b9dbde.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: NRT12-C3
X-Amz-Cf-Id: Gwzpjl0cD6DsTEVFsCRZnVaqCuGXr0DoETIVhjc9Y1FGF61vusxjJg==
Age: 585

Gzip

iwasa.takahito@hoge 20211219cloudfront % curl -H 'Accept-Encoding:gzip' -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
HTTP/1.1 200 OK
Content-Type: text/html
Server: AmazonS3
Content-Encoding: gzip
Vary: Accept-Encoding

Brotli

iwasa.takahito@hoge 20211219cloudfront % curl -H 'Accept-Encoding:br' -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html 
HTTP/1.1 200 OK
Content-Type: text/html
Content-Encoding: br
Vary: Accept-Encoding

GzipとBrotliが混在

多くのブラウザではGzipもBrotliもどちらもサポートされており、それをリクエスト時に伝えます。
その場合はAccept-Encodingにサポート形式が全て格納されて伝わります。

両方サポートされている場合、CloudFrontではBrotliを優先します。

iwasa.takahito@hoge 20211219cloudfront % curl -H 'Accept-Encoding:br,gzip' -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
HTTP/1.1 200 OK
Content-Type: text/html
Content-Encoding: br
Vary: Accept-Encoding

iwasa.takahito@hoge 20211219cloudfront % curl -H 'Accept-Encoding:gzip,br' -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
HTTP/1.1 200 OK
Content-Type: text/html
Content-Encoding: br
Vary: Accept-Encoding

なお、優先なので、CloudFront側のキャッシュポリシーでBrotliがサポートされていない場合はGzipが次点で選択されます。

iwasa.takahito@hoge 20211219cloudfront % curl -H 'Accept-Encoding:gzip,br' -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
HTTP/1.1 200 OK
Content-Type: text/html
Content-Encoding: gzip
Vary: Accept-Encoding

また、このキャッシュポリシー状態でクライアントがBrotliのみ要求する場合は無圧縮でレスポンスされます。

iwasa.takahito@hoge 20211219cloudfront % curl -H 'Accept-Encoding:br' -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
HTTP/1.1 200 OK
Content-Type: text/html
Vary: Accept-Encoding

キャッシュの確認

同一リクエストでもAccept-Encodingに応じて複数の圧縮形式でレスポンスされることがわかりました。

もうひとつこの記事で確認しておきたいのが、圧縮形式ごとのキャッシュの取り扱いです。
圧縮形式のサポート状況が異なる複数のブラウザからアクセスされた場合にどのような挙動になるでしょうか。

この時点ではキャッシュキーに明示的にAccept-Encodingは指定していません。
キャッシュを全て削除し、圧縮パターンごとに2回づつアクセスしたところ以下のような結果となりました。

iwasa.takahito@hoge 20211219cloudfront % curl -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
X-Cache: Miss from cloudfront

iwasa.takahito@hoge 20211219cloudfront % curl -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
X-Cache: Hit from cloudfront

iwasa.takahito@hoge 20211219cloudfront % curl -H 'Accept-Encoding:gzip' -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
Content-Encoding: gzip
X-Cache: Miss from cloudfront

iwasa.takahito@hoge 20211219cloudfront % curl -H 'Accept-Encoding:gzip' -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
Content-Encoding: gzip
X-Cache: Hit from cloudfront

iwasa.takahito@hoge 20211219cloudfront % curl -H 'Accept-Encoding:br' -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
Content-Encoding: br
X-Cache: Miss from cloudfront

iwasa.takahito@hoge 20211219cloudfront % curl -H 'Accept-Encoding:br' -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
Content-Encoding: br
X-Cache: Hit from cloudfront

それぞれの1回目のアクセスでキャッシュされていますね。
当然だとは思いますが、異なる圧縮形式間でキャッシュを共有してしまうことはありませんでした。

CloudFrontはキャッシュキーに自動でAccept-Encodingを含める仕様になっています。
逆に、明示的にキャッシュポリシーに指定した場合は圧縮しなくなってしまうようです。

念の為、異なるAccept-Encodingが指定された場合にキャッシュがクリアされてしまわないことも確認しました。

iwasa.takahito@hoge 20211219cloudfront % curl -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
X-Cache: Hit from cloudfront

iwasa.takahito@hoge 20211219cloudfront % curl -H 'Accept-Encoding:gzip' -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
Content-Encoding: gzip
X-Cache: Hit from cloudfront

iwasa.takahito@hoge 20211219cloudfront % curl -H 'Accept-Encoding:br' -I http://d3ob3s1x9vrcur.cloudfront.net/hoge.html
Content-Encoding: br
X-Cache: Hit from cloudfront

まとめ

本日は、Accept-Encodingを指定した圧縮の確認と形式ごとのキャッシュの取り扱いについて確認してみました。

  • CloudFrontはAccept-Encodingリクエストヘッダーに基づいてレスポンスの圧縮形式を判断している
  • Accept-Encodingを暗黙的にキャッシュキーに含まれてキャッシュされる

圧縮形式としてサポートされているのはgzipとbrですが、Accept-Encodingの標準仕様にCloudFrontが則っていることを確認することが出来ました。いいですね。