Varnish Cache完全ガイド:VCL設計と高速キャッシュ戦略でWebを最適化

Varnishとは

Varnish(一般には「Varnish Cache」と呼ばれる)は、高速なHTTPリバースプロキシ/キャッシュサーバです。静的ファイルや動的に生成されたページの結果をメモリ上にキャッシュしておき、バックエンド(例:Apache、Nginx、アプリケーションサーバ)へのリクエスト数とレスポンス遅延を大幅に削減します。大規模なトラフィックやバーストを扱う際に有効で、CDNやオリジンサーバの前段に置かれることが多いコンポーネントです。

基本的な特徴とアーキテクチャ

  • リバースプロキシ型: クライアントからのHTTP要求を受け取り、キャッシュされたレスポンスを返すかバックエンドに問い合わせます。
  • メモリ中心のストレージ: 高速な応答のためにメモリ(malloc)を主に使います。ファイルベースのストレージも設定可能ですが、性能面で差があります。
  • VCL(Varnish Configuration Language): 独自の設定言語でリクエスト処理の振る舞いを柔軟に定義できます。VCLは起動時にコンパイルされ、効率的に実行されます。
  • 細かなキャッシュ制御: TTL、grace(古いオブジェクトを一時的に返す)、バックグラウンドフェッチ(最初のリクエストで再取得を行いながら他は古いレスポンスを返す)など、実運用で必要な振る舞いを備えています。
  • 拡張性: VMOD(Varnish Modules)で機能拡張が可能。ログやヘッダ処理、ジオロケーションなど追加できます。

リクエスト処理の流れ(概念)

簡単に処理フローを追うと次の通りです(Varnishのフック名はバージョンにより細部が変わることがありますが概念は同じです)。

  • クライアントからの接続を受ける。
  • vcl_recvで要求を解析し、キャッシュ対象かを判断(pass=キャッシュしない、lookup=キャッシュ参照)。
  • キャッシュキー(URL+ヘッダ等)でハッシュ検索。ヒットすればvcl_hitで処理、ミスならバックエンドに問い合わせてvcl_backend_responseで保存可否を判断。
  • vcl_deliverでクライアントへ送信。また、条件によってはバックグラウンドでフェッチやバン(ban)による無効化を行う。

VCL(設定言語)の役割と例

VCLはVarnishの心臓部です。どのリクエストをキャッシュするか、どのヘッダをキャッシュキーに含めるか、Cookieの扱い、特定URLのみパスする等を決められます。VCLは起動時にC言語へと変換されネイティブ実行されるため高速です。

簡単なVCL例(GETのみキャッシュ、Cookieを持つ場合はpass):

vcl 4.0;
backend default { .host = "127.0.0.1"; .port = "8080"; }

sub vcl_recv {
  if (req.method != "GET" && req.method != "HEAD") {
    return (pass);
  }
  if (req.http.Cookie) {
    return (pass);
  }
}

sub vcl_backend_response {
  if (bereq.url ~ "\.(jpg|css|js|png)$") {
    set beresp.ttl = 7d;
  } else {
    set beresp.ttl = 1m;
  }
}

キャッシュ戦略のポイント

  • TTL(有効期限): beresp.ttlなどでオブジェクトの有効時間を制御します。
  • grace(グレース): バックエンドが遅い・不調なときに古いオブジェクトを一時的に返す機能。ユーザー体験を維持しつつバックエンド復旧を待てます。
  • バックグラウンドフェッチ: 一定条件で最初のリクエストをブロックせず、他のリクエストには古いレスポンスを返しつつ非同期で再取得することでヘビーな同時アクセスを緩和します。
  • 無効化(Purge / Ban): 特定URLや条件でキャッシュを削除・無効化できます。BANは条件式でマッチするオブジェクトをマークする方式で柔軟です。WordPress等のCMSではコンテンツ更新時に自動でPurgeを呼ぶ仕組みが一般的です。
  • キャッシュキー管理: Host、URL、Accept-Encoding、独自ヘッダなどキャッシュキーに含める要素は慎重に設計。不要な分割(キャッシュバラけ)を避け、誤った共有(キャッシュ汚染)を防ぎます。

運用上の注意点・監視

  • TLSは自前で終端: Varnish自体はTLS(HTTPS終端)を持たないため、Hitch、Nginx、HAProxy等でTLS終端を行い、平文HTTPでVarnishに渡すのが一般的です。
  • ログと統計: varnishlog、varnishncsa、varnishstat、varnishhist等のツールでアクセス/ヒット率/メモリ使用量を監視します。ヒット率(cache hit ratio)は主要な指標です。
  • 管理インターフェース: varnishadmによる管理や設定のリロードが可能。管理ポート(デフォルト6082)は外部に公開しないようにします。
  • スレッド・メモリチューニング: スレッドプールサイズやセッションワークスペース、ストレージサイズ(キャッシュ容量)を実負荷に合わせて調整します。

WordPress と Varnish の具体的連携

WordPressは認証やコメント投稿などでCookieを使うため、そのままだと多くのリクエストがキャッシュされません。実運用では次のような対応をします。

  • 管理領域(/wp-admin/など)やログインユーザーのリクエストを必ずpassする。
  • 公開ページはCache-ControlやExpiresヘッダ、またはVCLでberesp.ttlを設定してキャッシュする。
  • 記事更新時に自動でVarnishのPurge/BANを呼ぶプラグインを導入する(例:Varnish HTTP Purge プラグインなど)。
  • 動的に埋め込みたい部分はESI(Edge Side Includes)で分離することでページ全体はキャッシュしつつ一部のみ動的にレンダリングする手法が取れます。

セキュリティと落とし穴

  • 管理ポートの保護: varnishadm等の管理インターフェースはローカルアクセス限定か適切に認証・ファイアウォールで保護する。
  • キャッシュ汚染(Cache Poisoning): 不要なヘッダやCookieをキャッシュキーに含めたり、ユーザ毎の情報を誤って共有すると個人情報漏洩につながる。VCLで細かく管理する。
  • HTTPS終端の配置: TLS終端とVarnish間の接続を保護する(内部ネットワークでTLSを終端するか、信頼できるネットワーク内でのみ配置)ことを検討する。
  • ヘルスチェック: バックエンドのヘルスチェックやリトライ設定が不十分だと、障害時に期待通りにフェイルオーバーできない。

エコシステムと拡張

VarnishはVMODを通じて機能を拡張できます。代表的な用途はCookie操作、GeoIP判定、ログフォーマットの拡張など。また、TLS終端用のHitch、ロードバランサ(HAProxy)や監視ツールと組み合わせる運用が一般的です。さらに、商用のVarnish製品やサポート(Varnish Software)も存在します。

まとめ — どんな時にVarnishを使うか

Varnishは「高トラフィックを低レイテンシでさばき、バックエンド負荷を下げる」ことを目的に設計された強力なキャッシュソリューションです。静的コンテンツやキャッシュ可能な動的コンテンツが多いサイト、突発的なアクセス増に耐えたいオリジンサーバ、CDNではカバーしきれないカスタムキャッシュ戦略を必要とするケースに向いています。一方でTLS終端やユーザ個別の動的レスポンスを多用するアプリでは設計と運用の工夫が必要です。

参考文献