24

最近、Rails アプリケーション スタックに Varnish インスタンスを追加しました。デフォルト構成の Varnish は、次のように Cache-Control ヘッダーを使用して特定のリソースをキャッシュすることで確信できます。

Cache-Control: max-age=86400, public=true

コントローラーで expires_in ステートメントを使用してそれを達成しました。

def index
  expires_in 24.hours, public: true
  respond_with 'some content'
end

それはうまくいきました。私が予想していなかったのは、Cache-Control ヘッダーもブラウザーに影響を与えるということです。これは、Varnish とユーザーのブラウザーの両方が特定のリソースをキャッシュするという問題につながります。リソースは varnish から正しくパージされますが、ブラウザは max-age に達しない限りリソースを再リクエストしません。

では、Varnish と組み合わせて「expires_in」を使用する必要があるのでしょうか。Varnish の前にある Nginx または Apache インスタンスで Cache-Control ヘッダーをフィルタリングできますが、それは奇妙に思えます。

誰でも私を啓発できますか?

よろしくフェリックス

4

1 に答える 1

15

これは実際には非常に適切で有効な質問であり、リバース プロキシでは非常に一般的な質問です。

問題は、Cache-Control プロパティが 1 つしかなく、クライアント ブラウザ (プライベート キャッシュ) および/またはプロキシ サーバー (共有キャッシュ) を対象としていることです。サード パーティのプロキシにコンテンツをまったくキャッシュさせたくない場合、すべてのリクエストを Varnish (または Rails バックエンド) で処理したい場合は、Varnish から適切な Cache-Control ヘッダーを送信する必要があります。

バックエンドから送信される Cache-Control ヘッダーの変更については、https://www.varnish-cache.org/trac/wiki/VCLExampleLongerCachingで詳しく説明されています。

2 つの異なる角度からソリューションにアプローチできます。Rails バックエンドで max-age を定義する場合 (たとえば、オブジェクトごとに異なる TTL を指定する場合)、上記のリンクで説明されている方法を使用できます。

別の解決策は、バックエンドから Cache-Control ヘッダーをまったく送信せず、代わりに varnish vcl_fetch() でオブジェクトに望ましい TTL を定義することです。これが私たちが取ったアプローチです。

Varnish には 600 秒のデフォルトの TTL があり、変更が加えられたときに明確にパージされるページには、より長い TTL を定義します。現在の vcl_fetch() の定義は次のとおりです。

sub vcl_fetch {
  if (req.http.Host ~ "(forum|discus)") {
    # Forum pages are purged explicitly, so cache them for 48h
    set beresp.ttl = 48h;
  }

  if (req.url ~ "^/software/") {
    # Software pages are purged explicitly, so cache them for 48h
    set beresp.ttl = 48h;
  }

  if (req.url ~ "^/search/forum_search_results" ) {
    # We don't want forum search results to be cached for longer than 5 minutes
    set beresp.ttl = 300s;
  }

  if(req.url == "/robots.txt") {
    # Robots.txt is updated rarely and should be cached for 4 days
    # Purge manually as required
    set beresp.ttl = 96h;
  }

  if(beresp.status == 404) {
    # Cache 404 responses for 15 seconds
    set beresp.http.Cache-Control = "max-age=15";
    set beresp.ttl = 15s;
    set beresp.grace = 15s;
  }
}

この場合、Web バックエンド サーバーから Cache-Control ヘッダーをまったく送信しません。

于 2012-04-27T07:59:36.863 に答える