FastlyのTTL設定に関する問題のよくある原因

# この記事の内容について
この記事ではFastlyを利用した際にオブジェクトが思った通りキャッシュされない場合のよくある原因と確認すべき内容について説明します。


オブジェクトに設定されているTTLを確認する手順については以下のサイトを参照して下さい。
http://qiita.com/AtsushiFukuda/items/fb20f8a410b47396d83a



```
特に記載がない限り本記事の記載内容はデフォルト設定での挙動となります。
Fastlyの正式なサポート情報は https://docs.fastly.com/ を参照して下さい。
```

### キャッシュを行わない条件

Fastlyサーバーでは以下の条件の場合はキャッシュを行いません。

- HTTPリクエストのMethodがGETかHEAD以外の場合（例POST, PUT, DELETEなど)
- オリジンからのHTTPレスポンスにSet-Cookieが含まれている。
- オリジンからのレスポンスにCache-Control: private が含まれている
（Cache-Control: no-store, no-cache はキャッシュ対象となります）

まずはキャッシュされないリクエストが上記の条件に合致していないかを確認しましょう。


### Varyヘッダー

Cacheに影響を与えるヘッダーとしてはVaryヘッダーがあります。Varyヘッダーとは簡単にいうとFastlyサーバーなどのサーバーに「同じURLでもVaryヘッダーに指定されているヘッダーの内容が異なれば別オブジェクトとして取り扱いなさい」というオリジンサーバーからの命令となります。

VaryがあってもFastlyサーバーにキャッシュ自体は行われますが、例えばオリジンからのレスポンスに`Vary: User-Agent`というヘッダーが含まれる場合、同一のURLに対するリクエストでも、ChromeやFireFox、iPhoneのSafariなど、User-Agentが異なる場合は別々のオブジェクトとしてキャッシュが保持されます。

ここで注意が必要なのは、例えば同じChromeであってもブラウザのバージョンや適用しているパッチが違えばUser-Agentの値が異なるため別のオブジェクトとしてキャッシュされます。

そのため不用意にVaryを利用すると、キャッシュ効率が悪くなり、結果としてキャッシュヒット率の低下、オリジンオフロード率の低下とCDNサービスを適用するメリットが低下してしまいます。

Varyを利用する場合は、最小限のパターンを持つリクエストヘッダーをVaryに含めることがポイントとなります。

一般的にVaryに`Accept-Encoding`のみが指定されている場合は問題になることは少ないですが、それ以外のヘッダーがVaryに指定されている場合はキャッシュが効率的に行えていない可能性を疑ってみる必要があります。

特にWordPressやDrupalなどをCMSとして利用している場合、無条件でVaryにCookieなどが含まれている場合があるので注意が必要です。

オリジン側で本当に必要なヘッダー情報のみをVaryに指定するか、Fastlyサーバー側でVaryヘッダーの内容を無視するような設定を追加するなどの対処を検討しましょう。

VaryヘッダーがFastlyサーバー上の挙動に及ぼす影響については英文になってしまいますが
https://www.fastly.com/blog/best-practices-for-using-the-vary-header
のサイトに詳しく記載されています。


### FastlyサーバーのTTLの選択ロジック
Fastlyサーバーはオリジンサーバーからのレスポンスに含まれるCache-Controlヘッダーなどの値の内容に基づいてキャッシュするオブジェクトに設定するTTLを決定します。

TTLの設定に関連するヘッダーは何種類かあるのですが、以下の様な優先順位で適用するTTLが決定します。

1. `Set-Cookie`または`Cache-Control: private`を含む場合 → キャッシュしない
2. `Surrogate-Control: max-age=`ヘッダーに指定したTTL
3. `Cache-Control: s-maxage=`ヘッダーに指定したTTL
4. `Cache-Control: max-age=`ヘッダーに指定したTTL
5. `Expires:`ヘッダーに指定したTTL
6. Fastly設定上で指定されたFallback TTL(Default TTL)

つまり`Set-Cookie`や`Cache-Control: private`が存在する場合はSurrogate-ControlやExpiresヘッダーが存在していてもキャッシュが行われません。

`Surrogate-Control:max-age=120`と`Cache-Control: max-age=60`のふたつのヘッダーが存在する場合はSurrogate-Controlヘッダーが優先されますので、TTLとしては120秒が適用されることになります。

意図しないTTLが適用されている場合は上記の優先順位も確認して下さい。



### クエリストリングやSSLリクエストのキャッシュについて

Fastlyサーバーはデフォルトの設定ではリクエストされたHostとPathとクエリストリングをキャッシュされたオブジェクトを判断するための情報として利用します。

つまり以下のURLでいうと太字の部分がキャッシュを識別するキーとなります。
http://**www.sample.com/aaa.html?id=111**
http://**www.sample.com/aaa.html?id=222**

そのため上記のURLはそれぞれ別のページとしてキャッシュされます。

またキャッシュを行う際にSSLとNon−SSLは考慮されません。そのため以下のURLは同じオブジェクトとして扱われます。
**http**://www.sample.com/aaa.html?id=111
**https**://www.sample.com/aaa.html?id=111

SSLとNon-SSLで返却されるオブジェクト内容が異なる場合、SSLかどうかを示すヘッダーをVaryに設定することで問題を回避することが出来ます。

Varyにヘッダーを追加する手順は以下のページをご確認下さい。
https://docs.fastly.com/guides/vcl/manipulating-the-cache-key

### 404レスポンスなどの取り扱い

Fastlyは`404 Not Found` レスポンスも指定されたTTLの期間キャッシュを行います。
Fastlyがデフォルトでキャッシュを行うHTTPのレスポンスコードは以下の通りです。

| Code | Message |
|:-:|:-:|
|200	|OK|
|203	|Non-Authoritative Information|
|300	|Multiple Choices|
|301	|Moved Permanently|
|302	|Moved Temporarily|
|404	|Not Found|
|410	|Gone|

404レスポンスなど、特定のレスポンスコードの場合に通常とは異なるTTLを設定する手順は以下のページをご確認下さい。
https://docs.fastly.com/guides/basic-configuration/overriding-caching-defaults-based-on-a-backend-response



* * *

以上がキャッシュされているはずのオブジェクトがキャッシュされていないようにみえる場合のよくある原因です。

もちろんここで説明した以外のものが原因でキャッシュが正常に行われていないケースもありますが、思っている通りキャッシュされていないように思えるときはまずはこれらの内容を確認して見てください。