PASS アクションの挙動について

Varnish では Pass (キャッシュしない) をリクエスト設定で行うのとキャッシュ設定で行うのでは、異なる動作をトリガーします。リクエスト設定で Pass を設定すると、VCL では return(pass)vcl_recv することになります。キャッシュ設定で Pass を設定すると、return(pass)vcl_fetch されます。 キャッシュ設定で Pass を行うのは、Varnish 3+ での return(hit_for_pass) と同じ動作となります。

リクエスト設定での Pass

リクエスト設定で Pass を設定すると、生成された VCL の return(pass) 内で vcl_recv に出力されます。Varnish はオブジェクト内にオブジェクトがキャッシュされていないかどうかの確認(ルックアップ)を行わず、オリジンからのレスポンスもキャッシュされません。

キャッシュ設定

この方法での Pass ではリクエスト共有は行われません。通常、キャッシュにない同じオブジェクトに対して同時に複数のリクエストが発生すると、これらのリクエストは1つのリクエストとして集約され、1件のリクエストのみがオリジンに送信されます。最初のリクエストがオリジンに送信されている間、そのオブジェクトに対する他のリクエストは、レスポンスが受信されるまでキューに入れられます。リクエストが vcl_recv で Pass されると、それらのリクエストはすべて共有されることなく別々にオリジンに送信されます。

キャッシュ設定での Pass

キャッシュ設定で Pass を設定すると、生成された VCL の vcl_fetch 内で return(pass) に出力されます。リクエストのフローのこの時点では、Varnish はルックアップを実行し、オブジェクトがキャッシュに存在しないと判断しています。その後オリジンへリクエストが送られますが、vcl_fetch でレスポンスがキャッシュ不可能と判断されています。この動作は、Fastly のデフォルトの VCL では、オリジンからのレスポンスに Set-Cookie ヘッダーが存在する場合などに発生します。

キャッシュ設定

vcl_fetch での Pass は、リクエスト共有が無効にならないため、望ましくない場合がよくあります。これは、Varnish が vcl_recv の段階ではオブジェクトがキャッシュできないことを認識しないためです。後に vcl_fetch で Pass されるオブジェクトへの最初のリクエストでは、他のすべての同時キャッシュミスがキューに入れられます。オリジンからのレスポンスが受信 (vcl_fetch) され、リクエストが Pass されるべきことを Varnish が認識すると、キューに入れられたリクエストはオリジンに送信されます。

その結果、2人のユーザーが同時に同じオブジェクトをリクエストするケースでは、1人のユーザーのリクエストが処理されるまで、もう一方のユーザーが待機する必要があります。これに対して、これらのリクエストが vcl_recv で Pass された場合、どちらのユーザーにも待ち時間は発生しません。

このデメリットを回避するために、リクエストが vcl_fetch で Pass されると、Varnish は hit-for-pass オブジェクトと呼ばれるものを作成します。これらのオブジェクトは独自の TTL を持ち、TTL が有効な間、Varnish はこれらに対するリクエストを vcl_recv で Pass されたかのように処理します。そのため、vcl_fetch で Pass を行う際には用途にあった TTL を設定することが重要です。その後に発生するオブジェクトに対するすべてのリクエストは、hit-for-pass オブジェクトの TTL が期限切れになるまで Pass されます。hit-for-pass オブジェクトは他のオブジェクトと同様にパージすることも可能です。

ただし、この機能を利用しても、同時に発生したリクエストに対して待ち時間が発生する場合があります。キャッシュ内に hit-for-pass オブジェクトがない場合は常に、これらのリクエストは通常のキャッシュミスと同様に扱われ、リクエストの共有が有効になります。できるだけ vcl_fetch で Pass するのを避けるようにしてください。

req.hash_always_miss と req.hash_ignore_busy

req.hash_always_miss を設定すると、キャッシュにあるかどうかに関わらず、リクエストが強制的にミスとなります。これはレスポンスがキャッシュされ、リクエストの共有が無効にならないという点で vcl_recv で Pass する場合と異なります。必要に応じて後でリクエストを vcl_fetch で Pass することもできます。

関連する2つ目の変数に req.hash_ignore_busy があります。これを true に設定すると、リクエスト共有が無効になり、各リクエストが個別にオリジンに送信されます。req.hash_ignore_busy が有効な場合、すべてのレスポンスがキャッシュされ、オリジンから受信した各レスポンスによって最後のレスポンスが上書きされます。キャッシュにあるオブジェクトに対する今後のリクエストは、その前のキャッシュミスで取得したオブジェクトのコピーを受け取ります。req.hash_ignore_busy は主に、複数の Varnish を利用した複雑な環境においてデッドロックを避ける目的で使用されます。

これらの両方の変数を利用することで、レスポンスをキャッシュしながら、強制的にリクエストを個別にオリジンに送信することが可能となります。

Back to Top