FastlyサーバーのTTLの選択ロジック

# この記事の内容について

この記事ではFastlyを利用した際にサーバー上にキャッシュされる時間(TTL)の設定方法や、キャッシュ対象外となる条件などをまとめてみたいと思います。

```
特に記載がない限り本記事の記載内容はデフォルト設定での挙動となります。
この記事に記載さいれている内容の詳細は以下のURL等を参照して下さい
https://docs.fastly.com/guides/tutorials/cache-control-tutorial
```

他社CDNではTTLを設定する対象をURLのPathや拡張子単位で設定していくものもあるのですが、Fastlyではオリジンサーバーからの返却されるレスポンスヘッダーに設定されているCache-Controlなどのヘッダーの内容に基づいてTTLをコントロールします。

もちろんFastlyサーバー上でそれらのヘッダーを無視してTTLを設定(上書き)することも可能なのですが、この記事ではまず基本となるオリジンサーバーからのレスポンスヘッダー情報に基づいてTTLを選択するロジックを説明します。


## キャッシュしない条件
最初にキャッシュを行わない条件について理解しておきましょう。Fastlyサーバーでは以下の条件の場合はキャッシュを行いません。

- HTTPリクエストのMethodがGETかHEAD以外の場合（例POST, PUT, DELETEなど)

- オリジンからのHTTPレスポンスにSet-Cookieが含まれている。

- オリジンからのレスポンスのCache-Controlヘッダーに `private` が含まれている
（デフォルトでは **Cache-Control: no-store, no-cache はキャッシュ対象**です。）

- レスポンスコードが以下のもの**以外**である
200 OK
203 Non-Authoritative Information
300 Multiple Choices
301 Moved Permanently
302 Moved Temporarily
404 Not Found
410 Gone

これらの条件に適合すると Fastly サーバーはキャッシュを行いませんので注意しましょう。

なお、この動作はデフォルトで生成される以下の VCL コードで定義されています。必要に応じて挙動は変更することが可能です。


```:vcl_recv
    if (req.request != "HEAD" && req.request != "GET" && req.request != "FASTLYPURGE") {
      return(pass);
    }
```

```:vcl_fecth
  if (beresp.http.Set-Cookie) {
    set req.http.Fastly-Cachetype = "SETCOOKIE";
    return (pass);
  }
  if (beresp.http.Cache-Control ~ "private") {
    set req.http.Fastly-Cachetype = "PRIVATE";
    return (pass);
  }
```

カスタム VCL 利用時や UI で関連する設定を変更している場合の最終的な挙動は、生成された VCL のコードから確認して下さい。

※ カスタム VCL の標準のボイラープレート（テンプレート）を利用した場合、Cache-Control に `private` だけでなく `no-store` が含まれる場合もキャッシュ対象外になります。詳細はカスタム VCL 内の上記のコードを確認して下さい。


## TTLの設定ロジック
続いてFastlyサーバーがオリジンサーバーからのレスポンスヘッダーの内容に基づいてTTLを選択するロジックを説明します。

TTLの設定に関連するヘッダーは何種類かあるのですが、FastlyサーバーでのTTLに関連するヘッダーは`Cache-Control`, `Expires`, `Set-Cookie`, `Surrogate-Control`ヘッダーです。

これらのヘッダーの内容を参照し、以下のような優先順位で適用される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秒が適用されることになります。


なお、max-age, s-maxage, private以外の値がCache-Controlヘッダーに存在してもFastlyサーバーの挙動に影響は与えません。それらのヘッダーはそのままブラウザに送信されます。


# Fastly側でFallback TTL(Default TTL)を設定
オリジンからのレスポンスにSurrogate-ControlやCache-Control, Expiresが存在しない場合はFastly設定上で指定するTTLが適用されます。（上記の優先順位の6番の挙動）

特に追加で設定を行っていない場合、Serviceの設定画面の SettingカテゴリのFallback TTLで設定した内容が適用されます。

<img width="600" alt="001" src="https://qiita-image-store.s3.amazonaws.com/0/128569/5deaf42f-279d-3e40-dc9f-17e6b5832d93.jpeg">

### Default TTLをVCLコードから確認する
Fastlyのコントロールパネルで設定した内容はVanish Configuratin Languageとして生成されシステムに保存されます。
生成されたVCLは Servcieの画面の右上のOptionボタンから、Show VCL をクリックすると確認することが出来ます。設定された Default TTL をVCLコードから確認してみましょう。

![Fastly__Configure__Demo_Service_.jpg](https://qiita-image-store.s3.amazonaws.com/0/128569/996f143d-bca1-4dee-5f15-3e200c556bd2.jpeg)

Default TTLはvcl_fetch内の以下の場所で指定されています。

```
  if (beresp.http.Expires || beresp.http.Surrogate-Control ~ "max-age" || beresp.http.Cache-Control ~"(s-maxage|max-age)") {
    # keep the ttl here
  } else {
        # apply the default ttl
    set beresp.ttl = 3600s;
  }
```
コードを確認すると、上記の2から5の条件にマッチしない場合にDefault TTLで指定したTTLを適用していることが分かります。


## TTLの上書きと動作確認方法

以上がオリジンからのレスポンスに基づいてFastlyサーバーがTTLを選択するロジックとなります。

Fastlyサーバー側でTTLを設定（上書き）する手順については以下のサイトを参照して下さい。
http://qiita.com/AtsushiFukuda/items/258cf029585f901ea802

また、TTLが意図したどおりに設定されているかを確認する方法を以下を参照下さい。
http://qiita.com/AtsushiFukuda/items/fb20f8a410b47396d83a