LOG IN SIGN UP
Documentation

失効済みコンテンツの配信

  Last updated October 20, 2017

Fastly では、オリジンサーバーに問題が発生している時、またはオリジンサーバーからの新しいコンテンツの取得に長い時間を要している場合に、失効済みコンテンツ(キャッシュしてからTTLに設定された時間が経過したコンテンツ)を配信するよう設定することができます。例えば、Fastly からオリジンサーバーへの接続が失敗する場合、Fastly POP はユーザーのリクエストに対してキャッシュ済みコンテンツの配信を続けます。これらの機能は既定では有効になっていません。

新しいコンテンツの取得中に古いコンテンツを配信する

コンテンツによっては生成に時間がかかることがあります。コンテンツはキャッシュされ次第、すばやく配信できるようになりますが、最初にアクセスしようとするユーザーは生成されるのを待たなければなりません。

the caching time penalty

キャッシュがまったく存在しないならば、この状況を回避することはできません。一方で、コンテンツはキャッシュされているがその TTL が過ぎている場合、最新コンテンツを取得している間は有効期限切れのコンテンツを配信するよう、Fastly にて設定することが可能です。

fetching new content in the background

Mark Nottingham による RFC 5861 HTTP Cache-Control Extensions for Stale Content が定める仕様に基き、Fastly はこの機能を実装しています。この機能は Google の Chrome ブラウザへの導入が検討されています。

使用方法

この動作を有効にするには、 オリジンサーバーからのレスポンスの Cache-Control もしくは Surrogate-Control ヘッダーに、stale-while-revalidate または stale-if-error ステートメントを追加します。例えば、次のようにします。

Cache-Control: max-age=600, stale-while-revalidate=30

その結果、コンテンツを 10 分間キャッシュして、 その 10 分経過後の 30 秒間については、新たなコンテンツが取得されるまで失効済みのコンテンツを提供します。

同様に、 次のステートメントを指定した場合を考えてみましょう。

Surrogate-Control: max-age=3600, stale-if-error=86400

こうすると、キャッシュのコンテンツを 1 時間 (3600 秒) 毎に更新しますが、オリジンがダウンしている場合は期限切れのコンテンツを 1 日間 (86400 秒) 表示します。

別の方法として VCL 内でこれらの動作を制御することもできます。vcl_fetch に次の変数を設定してください。

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;

ただし、grace のステートメントが VCL 内に存在する場合、grace が優先されるため、Cache-Control または Surrogate-Control レスポンスヘッダー内の stale-while-revalidatestale-if-error のステートメントは無視されます。

beresp.stale_if_error を指定するだけでは、それがヘッダー内にあっても VCL に記載されていても、失効済みコンテンツの配信は機能しません。失効済みコンテンツの配信を行うには、以下の指示に従ってください。

エラー発生時に失効済みコンテンツを配信する

オリジンサーバーがダウンしている状況では、失効済みコンテンツを配信したほうがよいかもしれません。以下で説明する高度な設定方法では、オリジン障害のケース 3 つに対して VCL 内で対応しています。この設定を行うにはカスタム VCL のアップロード機能が有効化されている必要があります。

Varnish の処理において、オリジン障害には以下 3 つのケースが考えられます。

下記のカスタム VCL はこれら 3 種類のケースすべてに対応します。オリジンのヘルスステータス異常の場合、失効済みコンテンツの配信のデフォルト動作が stale-if-error により開始されます。オリジン障害の発生からオリジンのヘルスステータスが異常と見なされるまでの間、Varnish は通常 503 エラーを返します。このカスタム VCL では、失効済みキャッシュがある場合はそれを提供し、ない場合はシンセティック・エラーページを返します。このエラーページはカスタマイズ可能です。3 番目のケースを処理するために、vcl_fetch で 5XX エラーの発生を条件に、失効済みコンテンツまたはシンセティック・エラーページを提供します。

必須ではありませんが、この VCL と一緒にヘルスチェック機能を有効にしてください。ヘルスチェックを有効にしなくともすべての機能が動作しますが、オリジンのタイムアウトを待つため、失効済みコンテンツまたはシンセティック・レスポンスの配信が開始されるまでに待ち時間が発生します。ヘルスチェックを有効にすると、オリジンのヘルスステータスが異常であると把握されるため、待ち時間を省くことができます。

下記のカスタム VCL には、Fastly 標準のボイラープレートが含まれています。これをご利用のサービスにアップロードする前に、お客様のニーズに合わせて以下の値を修正または削除してください。

sub vcl_recv {
  if (req.http.Fastly-FF) {
    set req.max_stale_while_revalidate = 0s;
  }

#FASTLY recv

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

  return(lookup);
}

sub vcl_fetch {
  /* handle 5XX (or any other unwanted status code) */
  if (beresp.status >= 500 && beresp.status < 600) {

    /* deliver stale if the object is available */
    if (stale.exists) {
      return(deliver_stale);
    }

    if (req.restarts < 1 && (req.request == "GET" || req.request == "HEAD")) {
      restart;
    }

    /* else go to vcl_error to deliver a synthetic */
    error 503;
  }

  /* set stale_if_error and stale_while_revalidate (customize these values) */
  set beresp.stale_if_error = 86400s;
  set beresp.stale_while_revalidate = 60s;

#FASTLY fetch

  if ((beresp.status == 500 || beresp.status == 503) && req.restarts < 1 && (req.request == "GET" || req.request == "HEAD")) {
    restart;
  }

  if (req.restarts > 0) {
    set beresp.http.Fastly-Restarts = req.restarts;
  }

  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);
  }

  /* this code will never be run, commented out for clarity */
  /* if (beresp.status == 500 || beresp.status == 503) {
     set req.http.Fastly-Cachetype = "ERROR";
     set beresp.ttl = 1s;
     set beresp.grace = 5s;
     return(deliver);
  } */

  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;
  }

  return(deliver);
}

sub vcl_hit {
#FASTLY hit

  if (!obj.cacheable) {
    return(pass);
  }
  return(deliver);
}

sub vcl_miss {
#FASTLY miss
  return(fetch);
}

sub vcl_deliver {
  if (resp.status >= 500 && resp.status < 600) {
    /* restart if the stale object is available */
    if (stale.exists) {
      restart;
    }
  }

#FASTLY deliver
  return(deliver);
}

sub vcl_error {
#FASTLY error

  /* handle 503s */
  if (obj.status >= 500 && obj.status < 600) {

    /* deliver stale object if it is available */
    if (stale.exists) {
      return(deliver_stale);
    }

    /* otherwise, return a synthetic */

    /* include your HTML response here */
    synthetic {"<!DOCTYPE html><html>Replace this text with the error page you would like to serve to clients if your origin is offline.</html>"};
    return(deliver);
  }

}

sub vcl_pass {
#FASTLY pass
}

sub vcl_log {
#FASTLY log
}

失効済みコンテンツの配信が正常に機能しない場合のヒント

Fastly から失効済みコンテンツの配信がうまくいかない場合、以下について確認してください。

その他の参考資料


Back to Top