LOG IN SIGN UP
Documentation

古いコンテンツの配信

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

ある種のコンテンツは、生成までに時間がかかることがあります。コンテンツがキャッシュされたら、それはすぐに提供されますが、最初にアクセスしようとするユーザーには、そのような利点がありません。

the caching time penalty

キャッシュが完全にコールド状態の場合、 この問題を回避する手段はありませんが、 オブジェクトがキャッシュ内に存在し、 その TTL が失効している時には、 新たなコンテンツが取得されるまでの間古いコンテンツを表示するように Fastly を設定することができます。

fetching new content in the background

Fastly は、Mark Nottingham が提案する RFC 5861「HTTP Cache-Control Extensions for Stale Content」 の動作をベースにしています。 これは現在、Google の Chrome ブラウザへの導入が検討されています。

使用方法

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

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

wこの場合、 あるコンテンツを 10 分間キャッシュして、 10 分が経過したら新たなコンテンツが取得されるまで最高 30 秒間古いコンテンツを提供します。

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

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

この場合、キャッシュのコンテンツを毎時間 (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-while-revalidate または stale-if-error ステートメントよりも優先されます。

ヘッダまたは VCL で beresp.stale_if_error を設定した場合、それだけでは何の効果もありません。古いコンテンツを提供するには、以下の指示に従ってください。

Sエラー発生時の古いコンテンツの提供

オリジンサーバーが利用できなくなった状況で、 古いコンテンツを提供できる場合があります。 ここでは、 考えられる 3 種類のオリジン障害を VCL で処理するための、高度な設定について説明していきます。 これらの作業には、カスタム VCL のアップロード機能が必要です。

Varnish の観点では、オリジンに障害が発生する 3 種類の可能性が考えられます。

下記のカスタム VCL は、これらの 3 種類の事例すべてに対処します。オリジンが不健全な場合、デフォルトの古いコンテンツ提供動作が stale-if-error により開始されます。オリジンの障害から不健全と判断、マークされるまでの間、通常 Varnish は 503 を返します。このカスタム VCL では、古いコピーがある場合はそれを提供し、ない場合は synthetic エラーページを返します。このエラーページはカスタマイズできます。3 番目の事例を処理するために、vcl_fetch で 5XX エラーを傍受して、古いコンテンツまたは synthetic エラーページを提供します。

厳密に必要と言うわけではありませんが、この VCL と一緒にヘルスチェック機能を有効にしてください。ヘルスチェックを有効にしないでもすべての機能が動作しますが、オリジンのタイムアウトを待たなければならないため、古いコンテンツまたは synthetic response を提供するまで、非常に時間がかかってしまいます。ヘルスのチェックを有効にすると、オリジンが不健全だとマークされるため、この問題を回避することができます。

下記の 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>Please 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
}

その他の参考資料


Translations available [EN] English

翻訳についての注意事項