新しいデータをフェッチしている間に、ワニスがキャッシュから古いデータを送信できるようにしますか?


8

動的に生成されたページ(PHP-FPM、NGINX)をキャッシュし、その前にワニスを付けています。これは非常にうまく機能します。

ただし、キャッシュタイムアウトに達すると、次のようになります。

  • 新しいクライアントリクエストページ
  • ワニスはキャッシュタイムアウトを認識します
  • クライアントが待機する
  • ワニスはバックエンドから新しいページを取得します
  • varnishは新しいページをクライアントに配信します(また、すぐに取得する次のリクエストのためにページもキャッシュされます)

私がしたいのは:

  • クライアントリクエストページ
  • ワニスはタイムアウトを認識します
  • ニスは古いページをクライアントに配信します
  • ワニスはバックエンドから新しいページを取得してキャッシュに入れます

私の場合、特に数分からのキャッシュタイムアウトについて話しているときではなく、古い情報が非常に大きな問題を抱えているサイトではありません。

しかし、私はユーザーを罰せずに列に並んで待って、すぐに何かを届けたいとは思いません。それは何らかの方法で可能ですか?

例として、1分間キャッシュするように構成された私のサーバーに対してsiegeを5分間実行した場合の出力例を次に示します。

HTTP/1.1,200,  1.97,  12710,/,1,2013-06-24 00:21:06
...
HTTP/1.1,200,  1.88,  12710,/,1,2013-06-24 00:21:20
...
HTTP/1.1,200,  1.93,  12710,/,1,2013-06-24 00:22:08
...
HTTP/1.1,200,  1.89,  12710,/,1,2013-06-24 00:22:22
...
HTTP/1.1,200,  1.94,  12710,/,1,2013-06-24 00:23:10
...
HTTP/1.1,200,  1.91,  12709,/,1,2013-06-24 00:23:23
...
HTTP/1.1,200,  1.93,  12710,/,1,2013-06-24 00:24:12
...

実行中の何百ものリクエストを省略しまし0.02た。しかし、未加工のHTMLを2秒近く待たなければならないユーザーがいるのではないかと、私はまだ懸念しています。

ここでもっと上手くできないの?

(私はキャッシュ中にVarnishの送信に遭遇しました、それは同じように聞こえましたが、正確に私がやろうとしていることではありません。)

解決

Shane Maddenの回答には解決策が含まれていましたが、すぐにはわかりませんでした。関連性がないと思ったので質問に含めなかった別の詳細がありましたが、実際にはそうです。

私が現在使用しているCMSソリューションには、ニスデータベースリスナーがあり、コンテンツが変更されたページを禁止するようにニスに通知する機能があります。それはPURGEあるページを禁止するためにいくつかの正規表現でリクエストを送りました。

要約すると、私が不運なユーザーを獲得した2つのケースがあります。

  1. ページの通常のニスTTLが期限切れ
  2. バックエンドユーザーがコンテンツを変更すると、これによりニスにパージリクエストが送信されます

どちらの場合も、「不運な」ユーザーがいます。2番目のケースでは、バックエンドユーザーは通常、変更後にページをチェックするという事実によって緩和されます。必ずしもそうではありません。

それにもかかわらず、2番目のケースでは、ソリューションを作成しました(そうです、この質問は、最初のケースの答えを探すことから始まりました...私の側で不十分に定式化された質問)。

パージリクエストを送信する代わりに、Shanesの提案を使用してVCLを調整し、ワニスデータベースリスナーがにhash_always_miss設定されたページをフェッチする特別なリクエストを送信できるようにしましたtrue

現在のアーキテクチャでは、実際の非同期リクエストを実行する余裕は本当にありませんが、PHPで非同期GETリクエストを作成するにどうすればよいですか?私は、ページが読み込まれるのを待たずに、ワニスをトリガーしてバックエンドからページを取得してキャッシュするのに十分な、ワニスへのGETリクエストを作成できました。

正味の影響は、データベースリスナーがニスにリクエストを送信し、特定のページをポーリングしている間はリクエストが「不運」になることはありませんでしたが、ニスがバックエンドからページを完全にフェッチすると(300ミリ秒から2秒の範囲になる可能性があります)。突然そこにいた。

私はまだ、通常のTTLがなくなったときに同じ問題を回避する方法を見つける必要がありますが、解決策はShaneが提案するとおりです:wgetを使用してをトリガーするhash_always_missので、リストを取得するのに十分賢くする必要があります更新する必要があるページの数。

回答:


3

この問題を解決するために使用した解決策は、ページのTTLが更新される前に期限切れになる可能性がないことを確認することです。システムの1つで実行されているHTTPクライアントに、不運なクライアントの代わりに遅いロードを強制します。リクエスト。

私の場合、これはwgetcronで行われ、リクエストにマークを付ける特別なヘッダーを送信し、req.hash_always_missこれに基づいて設定し、コンテンツの新しいコピーを強制的にキャッシュにフェッチします。

acl purge {
    "localhost";
}

sub vcl_recv {
    /* other config here */
    if (req.http.X-Varnish-Nuke == "1" && client.ip ~ purge) {
        set req.hash_always_miss = true;
    }
    /* ... */
}

コンテンツの場合、これはVarnish TTLを5分程度に設定することを意味しますが、毎分キャッシュ更新要求を行うようにcron'd wgetを構成する必要があります。


私はあなたの意味を理解していると思います。これは単一のページではうまく機能しますが、他の何千ものページでも問題ありませんか?その規模ではcron / wgetを使用できません。
マーク

本質的に、少なくともどのページをキャッシュに保持したいかを宣言する必要があります。このリストがあれば、cronスクリプトのwgetが役に立たない理由はありません。
Falcon Momot 2013年

それがこの「ワニス外部アプローチ」の課題だと思います。最終的には、座って決定を下し、各ページにこれを実装する必要があります。ワニスに伝える方法はありません:「ttlが不足しましたか?新しいバージョンをフェッチしますが、それが発生するまで、古いバージョンを提供します」...?うーん。
マーク

4

@編集:

この機能がマスターブランチの最新バージョンに実装されたばかりのように見えることを簡単にお知らせします。おそらく、バージョンが真の古くなった改訂版をまだサポートしていない可能性があります/私が投稿した例が役立つでしょう貧弱なバグを1人抱える9999/10000リクエストは、バックエンドでリクエストが完了するのを待たなければなりません(それでも何もないよりはましです;)...


さて、前のコメントが機能していないと言っている理由は100%わかりませんが、https//www.varnish-software.com/static/book/Saving_a_request.htmlによると、

  • req.grace -Varnishがオブジェクトを猶予モードと見なすのにオブジェクトがどれだけ遅れるかを定義します。
  • beresp.grace -beresp.ttl-time Varnishがオブジェクトを保持する期間を定義します。
  • req.grace-多くの場合、バックエンドの状態に基づいてvcl_recvで変更されます。

私は現在、マニュアルに書かれているような設定を使用していて、問題なく動作しています...これが私のvclファイルのスニペットです...

sub vcl_recv {
    # Cache rules above here...
    if (req.backend.healthy) {
        set req.grace = 30d;
    } else {
        set req.grace = 300d;
    }
}

sub vcl_fetch {
    # Fetch rules above here ...

    # If backend returns 500 error then boost the cache grace period...
    if (beresp.status == 500) {
        set beresp.grace = 10h;
        return (restart);
    }

    # How long carnish should keep the objects in cache..
    set beresp.grace = 1h;

    # Actual TTL of cache - If an object is older than this an update will be triggered to the backend server :)
    set beresp.ttl = 1m;
}

より長いバックエンド応答猶予期間を提供したい場合(私の構成のように500エラーの場合)、バックエンドプローブをセットアップする必要があることに注意してください...これが私のバックエンドプローブのコピーです。

backend default {
    .host = "127.0.0.1";
    .port = "8080";
    .probe = { 
        .url = "/nginx-status";
        .timeout = 500 ms; 
        .interval = 3s; 
        .window = 10;
        .threshold = 4;
    }
}

これはvcl 4.0でも有効ですか?
ガデルカリーム

0

Varnish 3では、これは「猶予モード」によって実現されます。マニュアル[1]によると、次のロジックを追加する必要があります:

sub vcl_fetch {
  set beresp.grace = 30m;
} // Makes objects to be cached/stored 30 min beyond its max-age/ttl

sub vcl_recv {
  set req.grace = 60s;
} // Allows varnish to serve objects which expired within last minute.

[1] https://www.varnish-cache.org/docs/3.0/tutorial/handling_misbehaving_servers.html#grace-mode


これはOPの目標を達成できません。1つのクライアントは、バックエンドからコンテンツがフェッチされるのを待って遅延しますが、その背後にある他のクライアントには古い猶予結果が提供されます。「TTLの期限が切れると、コンテンツを要求する最初のクライアントは15秒間停止し、2番目のクライアントは猶予されたコピーを取得する必要があります。」- varnish-software.com/static/book/Saving_a_request.html
パックス

申し訳ありませんが、最初の有効期限が切れたリクエストで実際にどのように機能するかはわかりませんでした。
NITEMAN 2013年

おそらく、「バックグラウンドリクエスト」を
発する
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.