Webエンジニアの森脇です。
先日、Inside Frontend というフロントエンドのイベントがあり、チームメンバーが参加しました。参加メンバーから日経新聞社様の「日経電子版を速くする」について共有をしてもらい、弊社でも活用できそうな点は、取り入れさせて頂くことにしました。
日経電子版を速くする / nikkei-inside-frontend - Speaker Deck
資料の中で、Fastlyの「キャッシュの非同期更新」について紹介されています。弊社では、FastlyではなくVarnishを利用していますが、VarnishのGrace Modeでも同等のことが実現可能のため、今回は簡単な検証を兼ねて紹介します。
LCLでのVarnish活用については、以下の記事で紹介しています。
Grace Modeとは
キャッシュ有効期間(TTLで設定された期間)が過ぎた場合に置いても、 grace期間はキャッシュからレスポンスを返し、バックグラウンドでフェッチし、キャッシュオブジェクトを更新します。
これにより、クライアントにはなるべくキャッシュからレスポンスを返すとともに、キャッシュのオブジェクトを最新化できます。
図にするとこのような動きになると認識しています。
検証
graceの動きを簡単に検証します。
Varnishバージョン
varnish 4.1.9
シナリオ
- backendサーバ側では、現在時刻を表示するHTMLを返す
- ttl、graceは30sとする
vcl
sub vcl_backend_response { set beresp.ttl = 30s; set beresp.grace = 30s; }
初回アクセス
初回アクセスのため、backendからHTMLを取得し現在時刻が表示されます。
約25秒後に再アクセス
初回アクセスから30s以内のため、キャッシュされた時点での時刻が表示されます。
ttl: 4.556
約35秒後に再アクセス
初回アクセスから30sを過ぎていますが、grace期間内のためキャッシュされた時点での時刻が表示さます。
// 30sを過ぎているので、ttlはマイナスとなる ttl: -5.069
この時、バックグラウンドでフェッチされ、キャッシュが更新されます。
約36秒後にアクセス
前回のアクセスによって、キャッシュが更新されているため、前回アクセス日時が表示されます。
以上、簡単ですがgraceの動きを検証しました。
他ユースケースの紹介
次に、いくつかのユースケースに応じたVCLの定義を紹介します。
backendがエラーの場合のみ、graceを利用する
backendの状態によって、graceの利用有無を制御することも可能です。
まず、grace期間を1Hと長めに設定しておきます。
sub vcl_backend_response { set beresp.grace = 1h; }
vcl_hitで、backendの状態を見て、graceの利用有無を制御します。
sub vcl_hit { if (obj.ttl >= 0s) { // キャッシュを利用する return (deliver); } if (!std.healthy(req.backend_hint) && (obj.ttl + obj.grace > 0s)) { // backendがエラーの場合、grace期間内はキャッシュを利用する return (deliver); } else { return (fetch); } }
リクエストURLに応じて、grace期間を分ける
リクエストURLに応じて、graceの設定を変更することも可能です。
以下の例では、デフォルトは30sでトップページのみ300sにしています。
sub vcl_recv { if (req.url == "/") { set req.http.X-set-grace = "300s"; } } sub vcl_backend_response { set beresp.grace = std.duration(bereq.http.X-set-grace,30s); }
まとめ
graceをうまく利用することで、以下の要望をある程度は満たすことができます。
- キャッシュからレスポンスを返したい
- 新しいオブジェクトを返したい
ですが、適切なTTL/graceを設定するのはやはり難しく、弊社でも必要に応じて随時調整しています。今後も、継続的にパフォーマンス向上に取り組んでいきます。