ワニスを前に置いた遅いウェブアプリがあります。すべてのページは静的です(ユーザーごとに異なりません)が、最近のデータが含まれるように5分ごとに更新する必要があります。
簡単なスクリプトがあります(wget --mirror
)15分ごとにWebサイト全体をクロールします。各クロールには約5分かかります。クロールのポイントは、Varnishキャッシュ内のすべてのページを更新して、ユーザーがページの生成を待つ必要がないようにすることです(スパイダーのおかげで、すべてのページが最近生成されたため)。
タイムラインは次のようになります。
0:00:00から0:05:00の間に来るリクエストは、まだ更新されていないページにヒットする可能性があり、応答を数秒待つことを余儀なくされます。これは受け入れられません。
私がやりたいのは、おそらくVCLの魔法を使って、スパイダーからバックエンドへのリクエストを常に転送し、それでも応答をキャッシュに保存することです。このように、キャッシュの一部が空である5分間のウィンドウがないため、ユーザーはneverページが生成されるのを待つ必要はありません(おそらくサーバーの起動時を除いて)。
これどうやってするの?
req.hash_always_miss
トリックを行う必要があります。
スパイダーの実行の開始時にフルキャッシュフラッシュを実行しないでください。代わりに、スパイダーを機能するように設定するだけです-そしてあなたのvcl_recv
、常にキャッシュルックアップを見逃すようにスパイダーのリクエストを設定します。バックエンドから新しいコピーをフェッチします。
acl spider {
"127.0.0.1";
/* or whereever the spider comes from */
}
sub vcl_recv {
if (client.ip ~ spider) {
set req.hash_always_miss = true;
}
/* ... and continue as normal with the rest of the config */
}
それが発生している間、新しい応答がキャッシュに含まれるまで、クライアントは古いキャッシュをシームレスに提供し続けます(それがまだTTL内にある限り)。
上記のシェーンの答えはこれよりも優れています。これは、より複雑で追加の問題がある代替ソリューションです。これではなく、シェーンの回答に賛成してください。問題を解決する別の方法を示しています。
私の最初の考えは、_vcl_recv
_のreturn (pass);
でした。次に、リクエストがフェッチされた後、_vcl_fetch
_で、どういうわけか、Varnishにshould以前に具体的に渡されたとはいえ、オブジェクトをキャッシュします。
結局 これは不可能です :
以前のVCL関数(例:vcl_recv)でリクエストを渡すことを選択した場合でも、vcl_fetchのロジックを実行しますが、キャッシュ時間を指定してもオブジェクトはキャッシュに入りません。
したがって、次善の策は、通常の要求と同じようにルックアップをトリガーすることですが、常に失敗することを確認してください。ルックアッププロセスに影響を与える方法はないため、常にヒットします(isキャッシュされていると仮定します。キャッシュされていない場合は、とにかくミスして保存します)。しかし、私たちは_vcl_hit
_に影響を与えることができます:
_sub vcl_hit {
# is this our spider?
if (req.http.user-agent ~ "Wget" && client.ip ~ spider) {
# it's the spider, so purge the existing object
set obj.ttl = 0s;
return (restart);
}
return (deliver);
}
_
キャッシュを使用しないように強制することはできませんが、そのオブジェクトをキャッシュから削除して、プロセス全体を再開することはできます。ここで、最初の_vcl_recv
_に戻り、最終的に別のルックアップを実行します。更新しようとしているオブジェクトを既にパージしているため、オブジェクトは欠落し、データをフェッチしてキャッシュを更新します。
少し複雑ですが、機能します。ユーザーがパージと保存されている応答の間にスタックする唯一のウィンドウは、単一の要求が処理される時間です。完璧ではありませんが、かなり良いです。