うまいぼうぶろぐ

linuxとhttpdとperlのメモ

varnish cacheでコンテンツのキャッシュ

varnish cache

リバースプロキシ専用サーバ。キャッシュルールを細かく設定できるので、色々使えそうだし勉強がてら遊んでみた。

プロダクト環境で使ってなくて、backendはテスト用のapacheなので詳細なことはわかってないけど、まぁまぁ面白げ。

install

ubuntuとかならaptで入る。テストサーバが古いfedora coreだったし、せっかくなのでsourceで入れてみた。

$ wget http://sourceforge.net/projects/varnish/files/varnish/2.1.2/varnish-2.1.2.tar.gz/download
$ tar zxvf varnish-2.1.2.tar.gz
$ cd varnish-2.1.2
$ ./configure && make
$ su
# make install
### init、sysconfig ファイルコピー
# cd redhat
# cp varnish.sysconfig /etc/sysconfig/varnish
# cp varnish.initrc    /etc/init.d/varnish
### log出力用daemonのinitファイルコピー: 後述
# cp varnishlog.initrc  /etc/init.d/varnishlog
# cp varnishncsa.initrc /etc/init.d/varnishncsa

起動

単一のbackendホストに丸投げするだけならconfigいらず。

# varnishd -a :80 -b localhost:8080 -T localhost:6082 -f default.vcl
  • -a varnishdを80番でlisten
  • -b backendをlocalhost:8080
  • -T varnishdの管理ポートをlocalhost:6082で
  • -f vclファイルを指定

status確認

付属のvarnishstat, varnishtopコマンドで。他には管理ポートにtelnetしてstatsとかstatusを見てみる。

log確認

varnishdを起動するだけではログ出てこなくて、別のプロセスで取る模様。

varnishncsa

varnishncsaを起動しているとApache / NCSAの combinedのformatのログを取得できる。ログ解析をしたい場合などには必要かな。デフォルトは標準出力に出す。

option
  • -D

daemonで起動。

  • -a

logを上書きせずに追加する。

  • -f

logに出力するclientのIPアドレスを、X-Forwarded-Forヘッダの値で上書きする。
=> varnishの前にリバースプロキシがいてる場合などに使う?

  • -w

logfileを指定。varnishncsaはSIGHUPシグナルを受けると、logfileを開き直す。
=> log rotateの時に使う

varnishlog

varnishlogを起動していると、アクセスがある度にログが流れる。このログはvarnish用バイナリ形式?オプションはvarnishncsaとほぼ同じ。daemonで起動する場合はsampleのinitスクリプトなどで。

varnishの共有メモリから一時的に読む場合は、何もオプションつけずにvarnishlog を実行。ファイルに保存する場合は-a -w filename -D などで。(-a : append -D : daemonize)。保存したファイルから読む場合は varnishlog -r filename (テキスト形式ではないので、cat などでは読めない)。

varnish cache の設定ファイル

vclという書式。結構わかりやすい。

  • /usr/local/etc/varnish/default.vcl
  • /etc/varnish/default.vcl
構文のチェック

apachectl configtest みたいな構文をチェックするコマンド自体はないっぽい。ただ、varnishd -C でvcl言語をC言語に変換したコードを表示するオプションがあるので、これを使って

$ varnishd -C -f /path/to/default.vcl

とかすればいい。vclに間違いがあれば、このコマンド実行時にエラーになる。

syntax
  • backend

backendのapp serverとかを記述。

  • director

複数のbackendを1つのグループに設定。

未使用のbackend, director があるだけでエラーになるので注意。

  • action
    • pass

cacheしないで、backendサーバに聞きにいく

    • lookup

vcl_recvで。cacheを参照して返す。

  • vcl_recv sub routine

cilentからリクエストを受けたときに走る処理。HTTPメソッドとか、urlによる判別とか。

  • vcl_fetch sub routine

backendサーバからリクエストを受け取った後に走る処理。

  • vcl_hash sub routine

キャッシュのハッシュ値を何を元に計算するか。デフォルトはURL。user-agentを追加したいときは

sub vcl_hash {
  req.hash += req.url;
  req.hash += req.http.User-Agent; # これを追記
}

みたいに。

変数
  • req

request object

  • beresp

backend respons object

  • obj

cache object

tips

ていうほど大したこと試してないけど。

特定URLのTTLを変更

画像とかのTTL(Age ヘッダの上限) を長くする

sub vcl_fetch {
  if ( req.url ~ "\.(png|gif|jpg)$" ) {
     unset beresp.http.set-cookie;
     set beresp.ttl = 3600s;
  }
}
virtual host の設定例

backend で appサーバを定義して、vcl_recv 内でhostヘッダを見て振り分ける処理を書く。backend サーバがnamebaseのvirtualhost設定の場合はset req.http.host でhostヘッダを指定してないとダメ(なはず)。

backend www {
  .host = "192.168.0.1";
  .port = "80";
}

backend images {
  .host = "192.168.0.2";
  .port = "80";
}

sub vcl_recv {
  if (req.http.host ~ "^(www.)?example.com$") {
    set req.http.host = "www.example.com";
    set req.backend = www;
  } elsif (req.http.host ~ "^images.example.com$") {
    set req.http.host = "images.example.com";
    set req.backend = images;
  } else {
    error 404 "Unknown virtual host";
  }
}