kasei_sanのブログ

かせいさんのIT系のおぼえがきです。胡乱の方はnoteとtwitterへ

VarnishとVCLおぼえがき

Varnish とは

VCLについて

  • 手続き型言語
  • これだけでIP制限やbasic認証をかけられたりと意外に器用
  • 特定の処理ごとに、VCLに定義されたサブルーチンが呼びだされる(後述)

Varnishのcacheについて

  • cacheは hash と呼ばれる領域に格納される
  • すべてオンメモリなので高速(らしい
  • デフォルトでは、hashのキーはリクエストのURLとドメイン/IPアドレス
    • それとオリジンサーバの Varyヘッダ (後述) の組み合わせをキーにしてcacheが行われる
  • 後述する vcl_recv でcacheの可否。vcl_hash でhashのキーの定義ができる

Varyヘッダについて

  • キャッシュサーバに対して、どのようにcacheを分けるかを指示するための情報
  • オリジンサーバからのレスポンスヘッダに格納されている
  • 例えば Vary: Accept-Encoding ならば、Varnish側のhashキーが同一でも Accept-Encoding が異なるRequestは別の情報としてcacheされる

VCLでよく使う関数

  • include: 別のvclファイルをincludeする
  • set: 変数に値を格納する
  • unset: 変数の値を削除する
  • call: サブルーチンの呼び出し

VCLでよく使われる変数

サブルーチンによって、使えたり使えなかったりするので注意

  • client : クライアントの情報
  • server : サーバの情報
  • req : クライアントからのリクエスト
  • bereq : サーバに実際送るリクエスト
  • beresp: サーバから帰ってきたレスポンスヘッダ
  • resp: クライアントに返すレスポンスヘッダ

Varnishの処理の流れ

  • Requestを受け取った時や、hashのキーを決定するときなど、それぞれのタイミングで サブルーチン が呼ばれる
  • その サブルーチン を定義することで、独自の設定をVarnishに加えることができる
  • サブルーチンの流れは、こちらの公式ドキュメントを参照

ざっくりした流れ

vcl_recv

  • Requestを受けると最初に呼ばれるサブルーチン
    • 主に、hash , pass , pipe のいずれかを return の引数に入れる
    • hash : cacheする場合に選択。次はhashのキーを確定する vcl_cache が呼びだされる
    • pass : cacheしない場合に選択。次はpassした場合に呼び出される、 vcl_pass が呼び出される
    • pipe: 処理をパイプ(キャッシュサーバは何もせず、クライアントとサーバの通信をパイプするだけ)する場合に選択。次はpipeした場合に呼び出される、 vcl_pipe が呼び出される

vcl_pipe

  • vcl_recvreturn(pipe) したら来る
  • あんまりいじることはない。長い処理の場合、タイムアウト値を変更したりする

vcl_pass

  • vcl_recvreturn(pass) したら来る
  • passの場合だけリクエストヘッダをいじったりしたいときにはここに追記する
  • return(fetch) すれば、オリジンサーバに問い合わせをする直前のサブルーチン vcl_backend_fetch が呼び出される

vcl_hash

  • vcl_recvreturn(hash) したら来る
  • hashのキーを定義する
  • Varnishでは、cacheされたデータは hash に格納される
  • vcl_hash では、そのhashを取り出すためのキーを定義する
  • 関数 hash_data に値を追加していって、その値の組み合わせがキーになる
  • 最後に return (lookup) する
  • この後は、キーにhitするcacheがあれ vcl_hit 。無ければ、vcl_miss が呼び出される

参考

この場合、リクエストURLと、ホスト(もしくはipアドレス)の組み合わせがhashのキーとなっている

sub vcl_hash {
    hash_data(req.url);
    if (req.http.host) {
        hash_data(req.http.host);
    } else {
        hash_data(server.ip);
    }
    return (lookup);
}

ここに、webサービスの特性に応じてhash_dataを設定していく

  • スマホとPCでcacheを別にするとか
  • ログインユーザ毎に異なるcacheを表示するとか

vcl_hit

  • cacheがヒットした場合に呼び出される
  • return(deliver) すれば、vcl_deliver (cacheをクライアントにわたす直前のサブルーチン) が呼び出される
  • return(miss) すれば、vcl_miss (cacheがヒットしなかった場合のサブルーチン) が呼び出される

vcl_miss

  • cacheがヒットしなかった場合に呼び出される
  • return(fetch) すれば、オリジンサーバに問い合わせをする直前のサブルーチン vcl_backend_fetch が呼び出される

vcl_backend_fetch

  • オリジンサーバに問い合わせる直前のサブルーチン
  • Requestを加工したりするのはここ
  • return(fetch) すれば、オリジンサーバに問い合わせた後、vcl_backend_response が呼び出される

vcl_backend_response

  • オリジンサーバに問い合わせた後のサブルーチン
  • Responseを加工したりするのはここ
  • return(deliver) すれば、vcl_deliver (cacheをクライアントにわたす直前のサブルーチン) が呼び出される

vcl_deliver

  • クライアントに配信する直前のサブルーチン
  • vcl_hitvcl_backend_response の後に呼び出される
  • return(deliver) すると、クライアントにcacheが渡される

参考

👇 弊社blog記事。最初に読むと概要をつかみやすい

techblog.lclco.com

👇 v3.0.1 時代に作られたわかりやすい同人誌

blog.xcir.net

👇 公式ドキュメントのサブルーチンの流れの解説

varnish-cache.org

👇 公式ドキュメントのサブルーチンの解説

varnish-cache.org