FastlyにキャッシュされたオブジェクトのTTL確認方法

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

この記事ではFastlyを設定した際に意図したとおりにキャッシュされているかや適用されているTTLを確認する方法を説明します。


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

リクエストしたオブジェクトに設定されたTTLや、オブジェクトがキャッシュから返却されたかどうかをFastlyサーバーがレスポンスに付与するHTTPヘッダーから確認することが出来ます。

通常これらのデバッグ用のヘッダーはクライアントに返却するレスポンスには付与されません。これらのヘッダーをブラウザなどで確認したい場合はリクエストに`Fastly-Debug: 1`というヘッダーを付与する必要があります。

## Fastly-Debug ヘッダーの概要
まずこのFastly-Debugヘッダーで確認できる内容を説明します。

以下がFastlyサーバーから返却されるFastly Debug関連のヘッダーのサンプルです。

```
Fastly-Debug-Path: (D cache-lcy1128-LCY 1415969775) (F cache-lcy1130-LCY 1415969775) (D cache-sjc3132-SJC 1415969775) (F cache-sjc3128-SJC 1415969775)
Fastly-Debug-TTL: (M cache-lcy1128-LCY - - 0) (M cache-sjc3132-SJC - - 0)
X-Served-By: cache-sjc3132-SJC, cache-lcy1128-LCY
X-Cache: MISS, MISS
X-Cache-Hits: 0, 0
```
*X-Served-By, X-Cache, およびX-Cache-HitsヘッダーはリクエストにFastly-Debug: 1がなくても返却されます。*

**Fastly-Debug-Path**にはどのノードがfetch(オリジンからオブジェクトを取得)やdelivery(クライアントにオブジェクトを配信)を行ったかなどの情報が含まれます。Shielding（キャッシュノードの多段化）が設定されている場合はEdge PoPの情報が先に表示され、続いてShield Popの情報が表示されます。

なお、FastlyのPoPのロケーション情報は空港のコードで表されます。例えばNRTは東京、SJCはサンホゼのPoPを意味します。

- D: vcl_deliverを行ったedgeまはたshieldのnode
- F: vcl_fetchを行ったedgeまはたshieldのnode
- サーバー名の後に続く番号はunixtimeでのタイムスタンプです

**Fastly-Debug-TTL**にはTTLに関する様々な情報が含まれます。

```
Fastly-Debug-TTL: H cache-jfk1026-JFK 41733294.335 864000.000 2273
```

- H: Hitです。オブジェクトがキャッシュ上に見つかりました
- M: Missです。オブジェクトはキャッシュには見つかりませんでした

最初の数字はそのオブジェクトに残っているTTLです
ふたつ目の数字はgrace TTLと呼ばれるものです。
3つ目の数字はそのオブジェクトがキャッシュされてからの時間です

TTLを確認する場合はひとつめと3つ目の数字に注目して下さい。このふたつの数字を足した秒数がそのオブジェクトに設定されているTTLになります。

*この数字を生成するノードが限られているため、これらの数字が表示されるまでに数回アクセスが必要な場合があります*


**X-Served-By** はオブジェクトを配信したサーバーの情報が表示されます。

**X-Cache** はオブジェクトがキャッシュヒットしたかキャッシュミスしたかを表します。

**X-Cache-Hits** はキャッシュされたオブジェクトがヒットした回数を表します。（Fastly全体ではなく配信しているFastlyサーバーでキャッシュヒットした回数です）

X-Served-By, X-Cache, X-Cache-Hits は Shieldingを利用している場合はShield Popの情報が先に表示され、続いてEdge PoPの情報が表示されます。

例えば以下の場合は Shiled POP 上で 1回目の HIT で Edge POP 上では 4回目の HIT、ということになります。
```
< X-Cache: HIT, HIT
< X-Cache-Hits: 1, 4
```


これらのヘッダーの詳細は https://docs.fastly.com/guides/performance-tuning/understanding-cache-hit-and-miss-headers-with-shielded-services を参照して下さい。

**X-Timer**:はリクエストの処理時間に関する情報を提供します
X-Timerには以下のようフォーマットで返却されます
`S1392947468.641059399,VS0,VE0 (a cache HIT)`
`S1392951663.217806578,VS0,VE31 (a cache MISS)`

最初のSで始まる値はFastlyのEdgeでリクエストの処理が開始した時間(Unix Time)です。
その後のVSはVarnish Startの略で常に0が設定されます。
VEはVarnish Endの略で処理が完了するまでにかかった時間がミリセカンドで含まれます。
キャッシュヒットの場合は処理はミリセカンド以下で処理される事が多いため殆どのケースで0が記録されます。
上のVE31の例ではオリジンからコンテンツを取得し配信開始までに31ミリセカンドかかったことになります。

X-Timerの詳細は https://docs.fastly.com/guides/performance-tuning/understanding-the-xtimer-header.html を参照して下さい。

**Surrogate-Key**
コンテンツにSurrogate-Keyヘッダーを設定している場合は、Fastly-Debugヘッダーをリクエストに付与することで、Surrogate-Keyヘッダーの情報も返却するようになります。


### リクエストフローについて

Edge PoP、Shield PoPにそれぞれ2つのnodeの情報が記録されている場合がありあすが、これにはFastlyサーバー上でデフォルトで有効なClusteringという処理が関係しています。

Clusteringでは各PoP内でキャッシュオブジェクトを共有します。リクエストを受けたNodeにキャッシュが存在しない場合、そのNodeはPoP内のCluster NodeまたはShield Nodeと呼ばれる別のNodeにキャッシュが存在するかを確認します。

Cluster Nodeにもキャッシュが存在しない場合、リクエストを受けたNodeに代わってCluster Nodeがオリジンサーバーへオブジェクト取得リクエストを行います。

このためFastly_Debug Pathなどに同一PoP内の複数のNodeの情報が表示されます。

なお、このオリジンへのリクエストを担当するShield Nodeに対して、エンドユーザーからのリクエストを受けるNodeをEdge Nodeと呼びます。

Edge Nodeではvcl_recv, vcl_deliverが処理され、Shield Nodesではvcl_miss, vcl_hit, vcl_fetchが処理されます。



## curlコマンドでTTL情報を確認
それでは続いてFastly-Debugヘッダーを確認するための方法を説明します。前述したとおりリクエストに`Fastly-Debug: 1`を付与する必要があります。

まずはcurlコマンドを使ってこれを確認してみます。


curlはHTTPのリクエストをコマンドラインから行うためのコマンドラインツールです。Mac OSなどには標準でインストールされています。ツールの詳細やWindowsへのインストール方法は検索してみて下さい。


それではcurlを使ってwww.example.comにFastly Debugヘッダーをつけてリクエストを送ってみます。この場合のコマンドは以下のようになります。

`curl -svo /dev/null -H "Fastly-Debug:1" www.example.com`

なお、ここでは特に理解する必要はないですがcurlコマンドの各オプションの意味は以下のとおりです。

-s 沈黙モード。プログレスメーターやエラーメッセージを非表示にします
-v ヘッダー情報など処理情報の詳細を表示します
-o 取得したレスポンスを指定したPathに出力します。/dev/nullに出力していますので出力データを保存せずに破棄しています。
-H 指定した内容のヘッダーをリクエストに付与します。

"www.example.com" の部分はTTLを確認したいオブジェクトのURLに置き換えて下さい。もちろんFastlyを適用していないサイトに対してFastly-Debugヘッダーを送信してもデバッグ情報は返却されません。


## chromeでTTL情報を確認

### Fastly-Debugヘッダーの追加
chromeなどのブラウザからもヘッダーを付与してFastly-Debug情報を確認することが出来ます。
ヘッダーを追加するにはプラグインを利用するのが便利です。

同じような機能を提供するプラグインは複数あるのでどのプラグインを使っても大丈夫ですが、ここでは[Header-Editor](https://chrome.google.com/webstore/detail/header-editor/pkokmcnklmgbepioackopoknkdlhefjl?hl=ja)というプラグインを利用してヘッダーを追加してみます。

1. プラグインをインストールするとChromeの右上に鉛筆のようなアイコンが表示されますのでこれをクリックして下さい。
2. 以下の画面が表示されるので、HeaderとValueに以下の通り入力して下さい。
<img src="https://qiita-image-store.s3.amazonaws.com/0/128569/eef7853a-6f66-9967-c707-80ce0dee9b21.png" width=500>
 - Header : Fastly-Debug
 - Value : 1
 - Active : チェック

3. Addをクリック

これでリクエストに`Fastly-Debug: 1`が追加されます。それでは実際にヘッダー情報を確認してみます。


### Chrome開発者ツールでヘッダー情報を確認

1.Chromeのメニューから表示 → 開発/管理 → JavaScriptコンソール をクリックして下さい。
![Monosnap 2016-08-01 16-07-07.png](https://qiita-image-store.s3.amazonaws.com/0/128569/514a5bd5-3b01-1f1e-996a-0e8c53f70f11.png)
2.ブラウザ画面の下部に以下のような開発者コンソールが表示されますので、その中からNetworkをクリックして下さい。
![fastly.png (310×163) 2016-08-01 午後4時-24-49.png](https://qiita-image-store.s3.amazonaws.com/0/128569/eb1236b9-df07-a9cb-1b87-3dee84683a05.png)
3. TTLを確認したいURL、もしくはそのオブジェクトを含むページのURLをアドレスバーに入力してページを表示して下さい。
4. 開発者コンソールに取得したURLの一覧が表示されますので、ヘッダー情報を確認したいオブジェクトをクリックして下さい。ヘッダー情報が表示されます。



![fastly.png (310×163) 2016-08-01 午後4時-42-39.png](https://qiita-image-store.s3.amazonaws.com/0/128569/3235427c-7ac7-abbb-2049-9dd45dff844b.png)



5. Request Headerに正しく`Fastly-Debug: 1`が付与されていればResponse HeaderにFastly-Debugヘッダーが表示されているはずです。

上記のサンプルの場合、キャッシュの残り時間が3579秒、キャッシュされてからの時間が21秒ですのでこのオブジェクトに設定されているキャッシュのTTLは3600秒ということになります。

以上がFastly-Debugヘッダーを使ってオブジェクトに設定されたTTLを確認する方法になります。

FireFoxやIEなどのブラウザでも同様のツールやプラグインを利用することでTTLを確認することが可能です。




## レスポンスヘッダーに設定された TTL を含める

上述の Fastly-Debug ヘッダーを使用する方法とは別に、レスポンスの任意のヘッダーに設定された TTL の値を含めることも出来ます。

オブジェクトに設定された TTL は、vcl_fetch でのみ利用可能な `beresp.ttl` という変数に含まれています。ですので、vcl_fetch で `beresp.ttl` の値をレスポンスヘッダーに設定することで、クライアントへのレスポンスにも設定したヘッダーが追加されます。

実際の VCL のコードとしては以下のようになるので、VCL Snippet や Custom VCL を利用して追加します。

```:vcl_fetch
set beresp.http.ttl = beresp.ttl;
```

なお、vcl_fetch で TTL を上書きしている場合は上書き処理の後 `return(deliver);` 前にコードを追加するようご注意下さい。追加する場所によっては TTL を上書きする前の値が記録されてしまいます。