おぎろぐはてブロ

なんだかんだエンジニアになって10年以上

CloudFrontでgzip圧縮したデータを転送する

2015/12 追記

2015年12月にCloudFront Distributionの設定でエッジでgzip圧縮を行うことができるようになりました。便利!

aws.typepad.com

(以下、2013年8月時点での記事となります)

HTMLやCSSはgzipで圧縮して転送したいもの。ということで、CloudFrontでgzip転送する方法を確認したところ、簡単にできる感じでもなかったので軽くまとめる。 ドキュメントはここ

クライアントが Accept-Encoding: gzip をヘッダに含めてリクエストしてきたときのみに圧縮したデータを返却することができる。gzipのみ対応しており、deflateやsdchを指定されても無視する。

とはいえ Accept-Encoding を指定するだけで圧縮してくれるわけではない。これは、そのコンテンツを圧縮すべきかどうかの判断をする術がCloudFront側にないため。(圧縮率が悪いデータを圧縮・展開してもオーバーヘッドがかかるだけ、最悪サイズが増加してしまう場合もあって、一律圧縮するというのは効率がよくありません。)

オリジン側の対応についてみていく。

S3以外のカスタムオリジンの場合

オリジンをS3以外のApacheやNGINXなどのWebサーバを使う場合。

  1. webサーバ側でどのコンテンツを圧縮するか決めて設定する。拡張子を見て圧縮させるようなディレクティブを書いたりする
  2. ふつうにCloudFrontのディストリビューションを作成する
  3. webブラウザがCloudFrontのエッジにリクエストを飛ばす
  4. エッジはAccept-Encoding: gzipのヘッダがあれば、圧縮バージョンのキャッシュを探し、そうでなければ無圧縮のキャッシュを探す
  5. キャッシュがあればそれをwebブラウザに応答し、なければオリジンにリクエストを投げる
  6. エッジからのリクエストで、Accept-Encoding: gzipで且つ、上で圧縮対象にしたコンテンツならば圧縮されたデータを返却し、エッジにキャッシュされる

CloudFrontのエッジでは、圧縮されたものと、無圧縮なものと2パターンのキャッシュを保持するようになる感じ。Webサーバの設定は特に面倒なものではない。

S3がオリジンの場合

動的な生成などがなければ、S3をオリジンにすることが多いと思うのですが、カスタムオリジンよりも設定が面倒です。

  1. 圧縮対象のコンテンツについて、圧縮したものと、無圧縮のものと各2種類ずつデータを用意する。welcome.js があるとして、その圧縮版は welcome.js.gz。
  2. 両方をS3にアップロードする
  3. 圧縮したファイルについては、Content-Encoding: gzip のヘッダをManagement Consoleなどでつける
  4. 動的に生成するHTMLからCloudFrontへのリンクをする際に、クライアントが Accept-Encoding: gzip をヘッダに乗せてきたら welcome.js.gz の方を参照させる。

ということで、S3側はAccept-Encodingに応じて圧縮するとかそういった処理を行わないので、HTML生成時に動的にリンク先を変えろということ。

まとめ

  • CloudFrontは動的にgzip圧縮するようなことはなく、圧縮済みのデータを持たせることで対応する
  • S3をオリジンとした場合、Accept-Encodingを見て圧縮済みか未圧縮のデータを返すかという処理ができない

まだ続きます。。