いますぐ使う CloudFront

# CloudFrontとは

台数不明で性能不明ですが、グローバルに配置された、キャッシュサーバー。

# 効果

CloudFrontをリバースプロキシキャッシュとして立ててみました。お問い合わせページなど動的ページを除いて、ほぼ全部のリクエストをCloudFrontが捌いてくれてます。

![d0ff6181-11f1-d277-eee8-2d5999566133.jpg](https://qiita-image-store.s3.amazonaws.com/0/22947/5d9fa25e-3c99-a523-831e-a3364a3bb0c1.jpeg)

※効果には個人差がございます

# 課金ポイント

* [料金 \- Amazon CloudFront \| AWS](https://aws.amazon.com/jp/cloudfront/pricing/)
    * データ転送料金
    * キャッシュクリア料金
        * 1ファイル1回クリアが、月間1000回までは無料。以降は0.005 USD
            * リリースとかでこまめに大量のファイルをクリアすると、金かかる
            * キャッシュ有効期限は24時間。24時間ほっとけるならキャッシュクリア料金かからない

# 用語整理

* ひとつのCloudFrontは「ディストリビューション」。
    * EC2やRDSが「インスタンス」と呼んだように。
* キャッシュルールは「ビヘイビア」
* キャッシュ元データを配信するサーバーを「オリジン」
    * ELB、EC2、S3、その他のサーバー
* キャッシュクリアは「インバリデート」
    * 「無効化リクエスト」と書いてある文書もある

# CloudFront の設置場所

## CloudFront無しの構成

EC2のローカルディスクにすべてがあります。静的コンテンツ、動的ページ、すべてのアクセスを、EC2が捌く必要があります。ApacheとかNginxでキャッシュを効かせると、負荷は軽くなるかも。みたいな涙ぐましいノウハウがあったのです。

![f65e1219-60fe-d83f-c483-73b133b04544.jpg](https://qiita-image-store.s3.amazonaws.com/0/22947/bec02751-1e72-f42d-c930-50cd73208c30.jpeg)

## 横に置く

昔のCloudFrontは、GETとHEADしか受け付けなかったため、JS/CSS/画像/添付ファイルなどを配信するS3を別立てにして、その手前にCloudFrontを置いていました。HTMLの実装では、cssとかjs、画像のタグに書くのリンクを xxxxxxxx.cloudfront.com にしておくことで、こうできます。図ではS3に置くことにしていますが、リリースでのCSSやJSの同期とか、何かと状況が複雑になりがちです。

![40904824-cf46-b636-e04c-ee2462471b96.jpg](https://qiita-image-store.s3.amazonaws.com/0/22947/1abfcdb4-284c-f64e-7f9b-1b1b8aeecced.jpeg)

## 前に置く

[CloudFrontの2013年10月のアップデート](https://aws.amazon.com/jp/blogs/aws/amazon-cloudfront-content-uploads-post-put-other-methods/) から、すべてのHTTPメソッドを受けてくれるため、ウェブアプリサーバーの手前に置くことができます。この場合は、静的コンテンツはCloudFrontのキャッシュでリクエストを捌き、動的ページはCloudFrontはスルーさせて、EC2で処理させます。

![626b87d4-abd6-5ba8-6835-b3319f2722c0.jpg](https://qiita-image-store.s3.amazonaws.com/0/22947/c237ee72-3b61-e26c-1a93-db74bb0faf74.jpeg)

## 今からやるなら「前に置く」構成

CloudFront無しの構成に導入するなら、断然「前に置く」構成です。

ウェブアプリのソース改修不要で、CloudFrontを適切に設定して配置するだけでOKなので、面倒がないです。

ただし、特定のページだけIP制限してたりすると、ApacheやNginxの設定を変更する必要があります。

# とりあえずCloudFrontを立てる

必須項目だけ埋めて、あとで直せばOKです。

* AWSコンソールにはいる
* CloudFrontのページに行く
* Create Distribution
    * Webを選ぶ（RTMPは動画配信とかに使う用)
        * Origin Settings
            * Origin Domain Name
                * ELBエンドポイントURL、BeanstalkエンドポイントURL、S3エンドポイントURL、EC2 DNS名など
                * IPアドレスでなければOK
        * Default Cache Behavior Settings
            * あとで変えるので放置
        * Distribution Settings
            * Alternate Domain Names(CNAMEs)
                * このディストリビューションに当てる予定のドメイン名。
                * 「前に置く」構成なら、これまでELBに当てていたドメイン名を指定。
                * 「横に置く」構成なら、空欄でOK
        * 他はあとで変えればOKなので放置
        * Create Distributionボタン押す
* ディストリビューションは全世界に分散して立つのと、微妙にダサい仕様のため、しばらく時間がかかります

## ビヘイビアの掟

* ビヘイビアリストの上から順に評価されます。
* Default (*)は、
    * 一番下から動かせません。
    * 削除できません。
    * どのビヘイビアにも当たらなかった場合のため存在します。
* パスパターンにマッチしたら、そのビヘイビアだけに従って、キャッシュを見たり、オリジンにスルーしたりする
    * なので、ビヘイビアの上下の並び順は重要

## ビヘイビアの設定方針

下記のどちらか。後からでも変更はできますが、どっちで行くかを考えるために、先に切り分けておくと良いです。

* Default (*)を「キャッシュする」で書く。他のパスパターンは「キャッシュしない」で書く。
* Default (*)を「キャッシュしない」で書く。他のパスパターンは「キャッシュする」で書く。

## キャッシュしないページの設定

* Path Pattern
    * 仮に http://hoge.example.com/contact/piyo.jpg みたいなとき
        * /contact/piyo.jpg
        * /contact/*.jpg
        * *.jpg
    * みたいに、そのキャッシュルールを適用するパスパターンを指定します。
* Allowed HTTP Methods
    * 全部入りのを指定
* Forward Headers
    * 「all」を指定
* Object Caching
    * Customize
    * TTL(min, max, default)
        * ぜんぶゼロを指定
* Forward Cookies
    * 「all」を指定
* Query String Forwarding and Caching
    * 「forward all, cache based on all」を指定

## キャッシュするページの設定

* Path Pattern
    * 仮に http://hoge.example.com/contact/piyo.jpg みたいなとき
        * /contact/piyo.jpg
        * /contact/*.jpg
        * *.jpg
    * みたいに、そのキャッシュルールを適用するパスパターンを指定します。
* Allowed HTTP Methods
    * GET,HEAD を指定
* Forward Headers
    * 「Host」は必須。他にも必要なものがあれば追加。
* Object Caching
    * Use Origin Cache Headers
    * Customizeにして、TTLを入れてもOK
* Forward Cookies
    * Noneを指定
        * Whitelistにすべき場合もある
            * ウェブアプリの要件や、GAのトラッキングなどのため、
        * [CloudFrontで「Forward Cookies」を「All」にしている時に注意すべき点 ｜ Developers\.IO](http://dev.classmethod.jp/cloud/aws/sugano-007-cloudfront/)
    * ALLにすると、キャッシュの効きが、非常に、すこぶる悪くなる
* Query String Forwarding and Caching
    * 「forward all, cache based on all」を指定

## DNS設定

ビヘイビアふくめて、ディストリビューションの設定が完成したら、DNSの設定を書き換えます。

ディストリビューションには、「d1lxxxxxxxxx.cloudfront.net」のような、一意なドメイン名が発行されます。

Alternate Domain Names (CNAMEs)に入れたドメイン名のCNAMEとして、ディストリビューションのドメイン名を向けた、DNS CNAMEレコードを作成します。

## 動作確認

サイトにアクセスして、期待したとおりにビヘイビアが設定できているか、確認しましょう。

ChromeのデベロッパーツールのNetworkタブで、個々のファイルのレスポンスヘッダーに下記のようなのがあれば、CloudFrontを経由しています。

```
Via:1.1 41f313008af830d498dcb13814523bd7.cloudfront.net (CloudFront)
X-Amz-Cf-Id:xcP_6KiTFG_guNA9dRA-KOW6pg740-3mP1SvSrt2NqKGndWGPJKVuA==
X-Cache:Hit from cloudfront
```

X-Cacheに、キャッシュヒットしたかしてないかが記載されます。HitとMiss、ほかにもいくつかありますが、、、

* X-Cache:Hit from cloudfront
    * CloudFrontにあるキャッシュが返っています
* X-Cache:Miss from cloudfront
    * CloudFrontにキャッシュがなく、オリジンから返っています

HitとMissが想定と異なる場合は、ビヘイビアの調整が必要です。がんばりましょう。

# その他、TIPS

* サイト全体にIP制限を実施したい。社内向けテスト環境とかのため。
    * [【AWS】WAFを使ってIP制限を実施する \- Qiita](http://qiita.com/Yuki_BB3/items/3bca17836a43ea678450)
* サイトの一部だけIP制限を実施したい。管理者向けページとかのため。
    * [\[HOWTO\] Get real IP coming via AWS CloudFront and ELB to nginx – Medium](https://medium.com/@pahud/get-real-ip-coming-via-aws-cloudfront-and-elb-to-nginx-d418e5070976#.3pdsfqasz)
        * 「real_ip_recursive on;」がポイントですね
    * WAFや、ALBとの組み合わせで、なんかできそうな気もするけどなー、、。

# 制限、仕様

導入前に、CloudFrontというプロダクトの制限と仕様が、プロダクトの制限と仕様にマッチするのか、検討が必要です。

* 制限
    * [制限 \- Amazon CloudFront](http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html)
* 仕様
    * [カスタムオリジンの場合のリクエストとレスポンスの動作 \- Amazon CloudFront](http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html)
        * [リクエストのタイムアウト \- Amazon CloudFront](http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html#request-custom-request-timeout)
            * 30秒でタイムアウト。4秒 ~ 60秒の範囲で設定可能。
            * 長いようで短い。ファイルアップロードとか、KPIレポートページなどは、それなりに工夫しないと、簡単に超えてしまう。

# 参考文書

* [Amazon CloudFront の概要 \- Amazon CloudFront](http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/Introduction.html)
* [AWS再入門 Amazon CloudFront編 ｜ Developers\.IO](http://dev.classmethod.jp/cloud/cm-advent-calendar-2015-aws-re-entering-cloudfront/)
* [WP管理者必見！AWSで構築する新スケーラブルなWordPress構成〜CloudFront as Reverse Proxy ｜ Developers\.IO](http://dev.classmethod.jp/cloud/aws/wordpress_with_cloudfront_front-ended/)
* [CloudFrontで「Forward Cookies」を「All」にしている時に注意すべき点 ｜ Developers\.IO](http://dev.classmethod.jp/cloud/aws/sugano-007-cloudfront/)
* [Amazon CloudFrontのオリジンタイムアウトが変更できるようになりました ｜ Developers\.IO](https://dev.classmethod.jp/cloud/aws/change-cloudfront-origin-timeouts/)