2

Varnish (3.0.3) をロード バランサー/静的キャッシュとして 2 つの Web サーバーの前に置いています。Original Pull 方式を使用して CDN をセットアップしました。サイトの画像から手動で URL を取得し、CDN アドレスをドロップすると、元のプルが機能しており、画像が CDN にプルされて提供されていることを確認できます。

私のアプリケーションはかなり複雑で、この CDN をテストして Web アプリの速度が大幅に向上するかどうかを確認しているので、まだ CDN イメージを使用するように PHP コードを書き直す必要はありません。

私がやりたいことは、Varnish を設定して、イメージ ファイルに対して受信した要求を書き換え、クラスター内の 2 つの Apache サーバーから直接ではなく、CDN を介してそれらをプルすることです。

Varnish のドキュメントと、同様のことを行うためのオンラインのハウツーをいくつか読みましたが、正しく動作させることができず、ここで少し助けが必要です。

これを私が試したいくつかの異なる方法を次に示します(簡潔にするために編集しました)。

sub vcl_recv {
  #if request is image, redirect to CDN
  if (req.url ~ "\.(gif|ico|jpg|jpeg|png)$") {
        set req.http.host = "cdn.domain.com/";
        error 750 req.http.host + req.url;

    }

 }
sub vcl_error {
  if (obj.status == 750) {
    set obj.status = 302;
    set obj.http.Location = obj.response;
    return(deliver);
  }
}

それはうまくいきませんでした。その結果、どこでも壊れた画像が表示され、表示されたものはすべて .webp 拡張子を使用していたため、上記の条件では処理されていませんでした.

だから私はこれを試しました:

 backend cdn {
         .host = "cdn.domain.com";
         .port = "80";
}
sub vcl_recv {
  #if request is image, redirect to CDN
  if (req.url ~ "\.(gif|ico|jpg|jpeg|png)$") {

      set req.backend = cdn;
      return(lookup);
  }

}

これにより、ページにいくつかの画像が表示されましたが、ソースを表示すると、Apache サーバー (ドメイン名は CDN のドメイン名ではありませんでした) から来ているように見え、約半分の画像しか表示されていませんでした...おそらくブラウザーのキャッシュ.

ここでいくつかの入力が欲しいです、ありがとう。

この種のリダイレクトに Varnish を使用する方法はありませんか? Varnish の前に nginx を設定して、cdn へのリクエストを書き換えた方がよいでしょうか?

更新: 以下の両方の回答を使用して、リダイレクトが機能し、ACL を配置して、CDN がイメージを直接プルするのではなく、それ自体にリダイレクトできるようにします。ただし、ACL が自分の外部 IP を使用して接続を許可していることを確認しましたが、CDN はサーバーから新しいイメージを取得していません。イメージをローカル サーバーから CDN にプルして提供する代わりに、502 エラー (odd<) が発生します。これは私の vcl_recv のブロックが今のように見えるものです:

acl cdn {
     "ip.of.CDN";
}

sub vcl_recv {
  #if request is image, redirect to CDN
  if (req.url ~ "\.(gif|ico|jpg|jpeg|png)$") {
        if(!client.ip ~ cdn){
           error 750 "http://cdn.domain.com" + req.url;
        }
    }

 }
sub vcl_error {
  if (obj.status == 750) {
    set obj.status = 302;
    set obj.http.Location = obj.response;
    return(deliver);
  }
}
4

2 に答える 2

3

Varnish を使用すると、これを非常に簡単に行うことができます。nginx などをセットアップする必要はありません。実際、最初の解決策は、トリックを実行することに非常に近いものです。いくつかの変更が必要です。

sub vcl_recv {
  #if request is image, redirect to CDN
  if (req.url ~ "\.(gif|ico|jpg|jpeg|png)$") {
        error 750 "http://cdn.domain.com" + req.url;
    }
}
sub vcl_error {
  if (obj.status == 750) {
    set obj.status = 302;
    set obj.http.Location = obj.response;
    return(deliver);
  }
}

CDN URL の「http://」を忘れてしまいました。すべてreq.urlの s が / で始まるため、ホストの最後のスラッシュを省略できます。

vcl_errorまた、コードが で実行される最初のコードであることを確認する必要がありますvcl_error()。つまり、の定義が複数ある場合は、チェックに到達するvcl_error前にそれらのいずれも出力を配信しないことを確認してください。if (obj.status == 750)

このソリューションでは、すべてのクライアント ブラウザが最初にサーバーにクエリを実行し、次に 302 リダイレクトの後に CDN に別の要求を行うことに注意してください。これにより、各画像の読み込みに大幅な遅延が追加され、CDN がアプリのパフォーマンスを改善するかどうかを判断する最善の方法ではない可能性があります。

更新:オリジンからコンテンツをプルしようとしたときに CDN が 502 エラーを表示する問題について。リダイレクトを決定するためにリモート IP アドレスに依存することは、CDN が多数のサーバーを使用してプルを実行する可能性があり、アドレスが時間の経過とともに変化する可能性があるため、非常に危険です。これにより、VCL の保守が非常に面倒になり、エラーが発生しやすくなります。

CDN が使用する固有の仮想ホストをセットアップすることは可能でしょうか? たとえばoriginpull.domain.com、プライマリ アドレスではなくそのアドレスからコンテンツをプルするように CDN をセットアップしwww.domain.comますか?

vcl_recv()その後、次のように変更できます。

sub vcl_recv {
  #if request is image and request is not made from CDN, redirect to CDN
  if (req.http.host != "originpull.domain.com" &&
      req.url ~ "\.(gif|ico|jpg|jpeg|png)$") {
        error 750 "http://cdn.domain.com" + req.url;
    }
}

これにより、CDN からのリクエストがリダイレクトされなくなります。

于 2012-11-15T08:50:37.990 に答える
1

CDN がサイトからイメージのコピーをプルしており、手動でイメージを CDN にプッシュしていないと仮定します。リライトまたはバックエンド プロキシからの CDN ネットワークの単純な除外を見逃していませんか? CDN はサイトから画像のコピーを直接プルして、キャッシュにデータを入力できる必要があるためです。

Varnish で遊んでからしばらく経ちましたが、専門家ではありませんが、次の行に沿った何かが機能する可能性があります。

# Defnine the IP ranges of the CDN server.
acl cdn {
        "localhost";
        "11.22.33.0"/24;
}

...

    #if request is image, redirect to CDN, unless from the CDN
    if (req.url ~ "\.(gif|ico|jpg|jpeg|png)$") {
        if (!client.ip ~ cdn) {
            error 750 "http://cdn.domain.com" + req.url;
        }
    }
...
于 2012-11-15T14:09:21.257 に答える