失効済みコンテンツの配信
最終更新日 2021-04-21
Fastly では、オリジンサーバーに問題が発生している時、またはオリジンサーバーからの新しいコンテンツの取得に長い時間を要している場合に、失効済みコンテンツを配信するよう設定することができます。例えば、Fastly からオリジンサーバーに接続できない場合、Fastly POP はユーザーのリクエストに対してキャッシュ済みコンテンツの配信を続けます。これらの機能は既定では有効になっていません。
ヒント
失効済みコンテンツの配信に関する詳細は、失効済みコンテンツと再検証に関するドキュメントを参照してください。
新しいコンテンツの取得中に古いコンテンツを配信する
コンテンツの種類によっては、生成に時間がかかるものもあります。一度キャッシュされたコンテンツはすぐに配信されますが、最初にアクセスしようとしたユーザーはコンテンツが生成されるのを待たなければなりません。
これはコールドキャッシュの場合には避けられないことですが、オブジェクトがキャッシュにあり、 TTL が期限切れになっている時にこのようなことが起こるのであれば、Fastly は新しいコンテンツがバックグラウンドでフェッチされている間、失効済みコンテンツを表示するように設定することができます。
Fastly は、Google Chrome ブラウザへの搭載が検討されている Mark Nottingham 氏の RFC 5861 『HTTP Cache-Control Extensions for Stale Content』 で提案された動作をベースにしています。
失効済みの配信を有効にする
注意
すでにカスタム VCL でエラー時の失効済みコンテンツの配信を有効にしている場合、コントロールパネルでこの機能を追加すると、別の失効済み TTL が設定されます。これを回避するため、コントロールパネルでこの機能を有効化する前に、stale-if-error
ステートメントをカスタム VCL から削除してください。
コントロールパネルを介したエラーで、デフォルト TTL 期間 (43200秒または12時間) での失効済みコンテンツの配信を有効にするには、以下の手順に従ってください。
- Fastly コントロールパネルにログインします。
- Home ページから、適切なサービスを選択します。検索ボックスで ID、名称、ドメインによる検索が行えます。
- Edit configuration をクリックし、アクティブなバージョンをクローンするオプションを選択します。
- Settings をクリックします。
Serve stale スイッチをオンにすると、デフォルト TTL 期間である43200秒 (12時間) の間、失効済みコンテンツの配信が自動的に有効になります。
- Activate をクリックして設定への変更をデプロイします。
手動で失効済みの配信を有効にする
オリジンサーバーからのレスポンスの Cache-Control または Surrogate-Control ヘッダーに stale-while-revalidate
または stale-if-error
ディレクティブを追加することで、手動で失効済みコンテンツの配信を有効にすることができます。例:
Cache-Control: max-age=600, stale-while-revalidate=30
この例では、一部のコンテンツを10分間キャッシュした後、新しいコンテンツが取得されるまでの間、最大30秒間失効済みコンテンツを配信するようになっています。
同様に、 こちらのステートメント:
Surrogate-Control: max-age=3600, stale-if-error=86400
では、キャッシュのコンテンツを1時間 (3600 秒) 毎に更新しますが、オリジンがダウンしている場合は期限切れのコンテンツを1日間 (86400 秒) 表示するようになっています。
また、vcl_fetch
にて以下の変数を設定することで、VCL 内からこれらの動作を制御することもできます。。
set beresp.stale_while_revalidate = 30s;
set beresp.stale_if_error = 86400s;
grace によるインタラクション
Stale-if-error は、Varnish の変数 grace と全く同じ働きをするので、この2つの記述は同等です。
set beresp.grace = 86400s;
set beresp.stale_if_error = 86400s;
ただし、VCL に grace のステートメントがある場合は、Cache-Control や Surrogate-Control のレスポンスヘッダー内の stale-if-error
ステートメントをオーバーライドします。
ヘッダーや VCL で beresp.stale_if_error
を設定するだけでは何の意味もありません。失効済みコンテンツを配信するためには、以下の手順を踏む必要があります。
エラー発生時に失効済みコンテンツを配信する
オリジンサーバーが利用できなくなった場合に、失効済みコンテンツを配信したい場合があります。この手順では、3つのオリジンサーバーの障害のシナリオにて VCL を使って対応するための高度な設定を行います。
Varnish の場合、オリジン/オリジンサーバー障害には3つのケースが考えられます。
- ヘルスチェックの失敗により、オリジン/オリジンサーバーに異常があると見なされる。
- 何らかの理由で Varnish がオリジン/オリジンサーバーに接続できない場合、503エラーが発生する。
- オリジンからの HTTP レスポンスが、ユーザーへの配信に適さない内容である (503エラーなど)。
下記のカスタム VCL はこれら3種類のケースすべてに対応します。オリジンのヘルスステータスが異常の場合、デフォルトサーバーの執行済み動作がstale-if-error
によって開始されます。オリジン/オリジンサーバー障害の発生からオリジンのヘルスステータスが異常と見なされるまでの間、Varnish は通常503 エラーを返します。カスタム VCL を使用することで、失効済みのコピーがある場合には、代わりに失効済みを配信するか、シンセティックエラーページを返すことができます。エラーページはカスタマイズすることができます。3つ目のケースでは、vcl_fetch
での 5XX エラーを遮断し、失効済みコンテンツを配信するか、シンセティックエラーページを配信することで対応することができます。
必須ではありませんが、この VCL と一緒にヘルスチェック機能を有効にしてください。ヘルスチェックを有効にしていない場合でもすべての機能は動作しますが、失効済みのレスポンスやシンセティックレスポンスの配信には、オリジンのタイムアウトを待たなくてはいけないため、より長い時間がかかります。ヘルスチェックを有効にすると、オリジンが不健全であるとマークされるため、この問題は回避されます。
以下のカスタム VCL は、Fastly 標準のボイラープレートを含んでいます。お客様のサービスにアップロードする前に、必要に合わせて以下の値をカスタマイズまたは削除してください。
if (beresp.status >= 500 && beresp.status < 600)
は、失効済みコンテンツやシンセティックレスポンスを配信すべき HTTP レスポンスコードを含むように変更する必要があります。set beresp.stale_if_error = 86400s;
は、失効済みコンテンツが配信される期間を制御します。この値は、設定に応じて適切な値に設定する必要があります。オリジンから Surrogate-Control または Cache-Control にてstale_if_error
を送信している場合は、この行全体を削除します。set beresp.stale_while_revalidate = 60s;
これは、オブジェクトstale_while_revalidate
に対して機能が有効になる時間を制御するもので、設定に意味のある量に設定する必要があります。この機能により、Varnish はキャッシュミスの際に執行済みとなり、バックグラウンドでオリジンから最新バージョンのオブジェクトを取得するようになります。これにより、TTL の短いオブジェクトや、一般的なキャッシュミスの際に、大きなパフォーマンスの向上が期待できます。stale_while_revalidate
は、stale_if_error
によって上書きされるので注意してください。つまり、オブジェクトが再検証中に失効済み(キャッシュしてからTTLに設定された時間が経過した)状態で配信される資格がある限り、stale_if_error
の効果はありません。オリジンから Surrogate-Control または Cache-Control にてstale_while_revalidate
を送信している場合は、この行全体を削除します。synthetic {"<!DOCTYPE html>Your HTML!</html>"};
は、失効済みバージョンのオブジェクトが存在しない場合に Varnish が返すシンセティックレスポンスであり、設定に応じて適切に設定する必要があります。ここには、お客様の HTML、CSS、JS を埋め込むことができます。外部の CSS や JS ドキュメントを参照する際には注意が必要です。オリジンがオフラインの場合は、それらも利用できない可能性があります。
1sub vcl_recv {2 /* if shielding is enabled, the below code is required */3 if (fastly.ff.visits_this_service != 0) {4 set req.max_stale_while_revalidate = 0s;5 }6#FASTLY recv7 if (req.method != "HEAD" && req.method != "GET" && req.method != "FASTLYPURGE") {8 return(pass);9 }10 return(lookup);11}12sub vcl_fetch {13 /* handle 5XX (or any other unwanted status code) */14 if (beresp.status >= 500 && beresp.status < 600) {15 /* deliver stale if the object is available */16 if (stale.exists) {17 return(deliver_stale);18 }19 if (req.restarts < 1 && (req.method == "GET" || req.method == "HEAD")) {20 restart;21 }22 /* else go to vcl_error to deliver a synthetic */23 error beresp.status;24 }25 /* set stale_if_error and stale_while_revalidate (customize these values) */26 set beresp.stale_if_error = 86400s;27 set beresp.stale_while_revalidate = 60s;28#FASTLY fetch29 if ((beresp.status == 500 || beresp.status == 503) && req.restarts < 1 && (req.method == "GET" || req.method == "HEAD")) {30 restart;31 }32 if (req.restarts > 0) {33 set beresp.http.Fastly-Restarts = req.restarts;34 }35 if (beresp.http.Set-Cookie) {36 set req.http.Fastly-Cachetype = "SETCOOKIE";37 return(pass);38 }39 if (beresp.http.Cache-Control ~ "private") {40 set req.http.Fastly-Cachetype = "PRIVATE";41 return(pass);42 }43 /* this code will never be run, commented out for clarity */44 /* if (beresp.status == 500 || beresp.status == 503) {45 set req.http.Fastly-Cachetype = "ERROR";46 set beresp.ttl = 1s;47 set beresp.grace = 5s;48 return(deliver);49 } */50 if (beresp.http.Expires || beresp.http.Surrogate-Control ~ "max-age" || beresp.http.Cache-Control ~ "(s-maxage|max-age)") {51 # keep the ttl here52 } else {53 # apply the default ttl54 set beresp.ttl = 3600s;55 }56 return(deliver);57}58sub vcl_hit {59#FASTLY hit60 if (!obj.cacheable) {61 return(pass);62 }63 return(deliver);64}65sub vcl_miss {66#FASTLY miss67 return(fetch);68}69sub vcl_deliver {70#FASTLY deliver71 return(deliver);72}73sub vcl_error {74#FASTLY error75 /* handle 503s */76 if (obj.status >= 500 && obj.status < 600) {77 /* deliver stale object if it is available */78 if (stale.exists) {79 return(deliver_stale);80 }81 /* otherwise, return a synthetic */82 /* include your HTML response here */83 synthetic {"<!DOCTYPE html><html>Replace this text with the error page you would like to serve to clients if your origin is offline.</html>"};84 return(deliver);85 }86}87sub vcl_pass {88#FASTLY pass89}90sub vcl_log {91#FASTLY log92}
失効済みコンテンツの配信が期待通りにいかない理由
Fastly からの失効済みコンテンツの配信が行われない場合、以下のポイントを確認してください。
- キャッシュ: 失効済みオブジェクトは、キャッシュ可能なコンテンツにのみ有効です。
- VCL:
req.hash_always_miss
またはreq.hash_ignore_busy
の変数をtrue
にすると、stale-while-revalidate
の効果が無効になります。 - オリジンシールド:オリジンシールドを有効にしていない場合、POPは、そのキャッシュ可能なオブジェクトへのリクエストが以前にそのPOPを介して行われた場合にのみ、エラー時に執行済みとなります。エラー発生時に失効済みコンテンツがキャッシュされる確率を高めるため、オリジンシールドを有効にすることを推奨します。オリジンシールドはまた、全コンテンツのパージ実行後に速やかにコンテンツをキャッシュさせるためにも効果的です。
- リクエスト: サイトへのトラフィックが増加すると、オリジンシールドが無効な場合でも、失効済みオブジェクトが利用可能になる可能性が高くなります。人気のあるコンテンツならば、複数の POP にてキャッシュされることもあります。
- 最近使用していない場合(URL):Fastly は LRU リストを採用しているため、オブジェクトは TTL (キャッシュ保持時間) の期間中に継続的にキャッシュを保持することを必ずしも保証しません。キャッシュの保持と削除は、ファイルに対するリクエストの頻度、TTL の値、ファイルの配信元となる POP など、数多くの要因を踏まえて行われます。例えば、3700秒以上の TTL のファイルがディスクへ保管される一方で、3700秒未満の TTL の場合はメモリーのみに一時的に保管されます。TTL は可能な限り3700秒以上に設定することをお勧めします。
- パージ: パージの際は、可能な限りソフトパージを実行してコンテンツをバージしください。ソフトパージでは、Fastly のキャッシュからコンテンツを永久に削除するのではなく、古い (失効済み) コンテンツとして簡単にマークすることができます。ソフトパージが不可能ならば、全コンテンツのパージをできる限り避けて、URL によるパージかキーによるパージの活用を推奨します。
翻訳についての注意事項
このフォームを使用して機密性の高い情報を送信しないでください。サポートが必要な場合は、サポートチームまでご連絡ください。このフォームは reCAPTCHA によって保護されており、Google のプライバシーポリシーと利用規約が適用されます。