- 2013-12-06 (金) 13:00
- Advent Calendar 2013 | AWS | PHP | Web+DB
Shin x blog Advent Calendar 2013 の 6 日目です。
とあるサイトに、Varnish をリバースプロキシとして導入して、半年が経過しました。
導入した経緯やその効果など書いてみたいと思います。
Varnish とは
Varnish は、HTTP アクセラレータです。Web サーバのリバースプロキシとして動作し、キャッシュを生かして高いパフォーマンスを発揮するのが特徴です。また、VCL という独自の設定言語を持ち、これにより状況に応じた設定を柔軟に行うことができます。
導入の経緯
このサイトでは LAMP 構成の CMS を利用しており、インフラには AWS を利用しています。基本、閲覧が中心なのですが、イベント時に多数のアクセスがあります。S3 や CloudFront も検討したのですが、コンテンツを数分おきに更新する必要があるので今回は採用しませんでした。
下記が構成のイメージです。なお図はかなり簡略化しており、実際の構成とは異なります。
こちらでパフォーマンスの問題が発生したので、CMS が生成したページ全体をキャッシュとして高速に返すよう Varnish Cache を導入しました。
当初、nginx の proxy_cache を試したのですが、同一 URL へ多数のリクエストが来ている状況でキャッシュのライフタイムが切れると、バックエンドへ同じ URL に対して複数のリクエストが飛んでしまい、PHP アプリケーション側に負荷がかかるという現象があったので、今回は取りやめました。
Varnish では、同一 URL に対して複数のリクエストがあっても、バックエンドへは 1 リクエストしか飛ばないようになっています。
導入
Varnish Cache は、m1.large インスタンスの Amazon Linux サーバに yum からインストールしました。
$ sudo rpm --nosignature -ivh http://repo.varnish-cache.org/redhat/varnish-3.0/el6/noarch/varnish-release/varnish-release-3.0-1.el6.noarch.rpm $ sudo yum -y install varnish
もし varnish のプロセスが落ちた場合に自動で再起動するように monit も入れています。varnish は、monit から起動しています。
$ sudo yum install monit $ sudo chkconfig monit on $ sudo vim /etc/monit.d/varnish check process varnish with pidfile /var/run/varnishd.pid start program = "/etc/init.d/varnish start" stop program = "/etc/init.d/varnish stop" $ sudo service monit start
監視
死活、性能監視として Zabbix を採用していたので、Varnish サーバも Zabbix で監視しています。
Zabbix のテンプレートは下記を利用しています。
効果
Varnish 導入の効果はてきめんでした。
ELB 経由で来たリクエストは全て Varnish を経由しており、キャッシュが有効な期間(3分で設定しています)は、キャッシュを返すだけなので非常に高速です。
またキャッシュが切れた場合も、バックエンドへは 1 URL に対して 1 リクエストしか来ないため、バックエンドへの大きな負荷にはなりません。(ある特定の数ページのみが際立ってアクセスされるサイトなので)
導入前は、ピーク時にはバックエンドの Web サーバが応答を返せない場合があったのですが、それも一切無くなりました。
はっきりいって、下手に CMS を細々チューニングするよりも遥かに効果があります。導入後も安定して動いており、Varnish 起因の問題も発生していません。
参考の数値として、270,000 req/m のリクエストが来た時(Varnish 上位にある ELB の RequestCount)、Varnishサーバ(m1.large)の CPU 利用率は 56% 程度でした。その際の Client requests received(client_req)は 5,000 弱でした。外部からの閲覧に関して遅延など異常はありませんでした。
VCL
Varnish の特徴として挙げられるのが VCL = Varnish configuation Language による設定です。
VCL は小さな DSL となっており、プログラミングのように設定を書くことができます。イメージとしては nginx の設定をよりコードっぽくした感じですね。
例えば、下記は UserAgent を見て、iPhone が含まれていたら、http://sp.example.com/ へリダイレクトさせる VCL です。
if (req.url == "/") { if (req.http.user-agent ~ "(?i)iPhone") { error 750 "Moved Temporarily"; } } sub vcl_error { if (obj.status == 750) { set obj.http.location = "https://sp.example.com/"; set obj.status = 302; return (deliver); } }
参考
構築にあたって参考にしたサイトです。柔軟に設定できるので、色々と調べながらの調整になりました。
-
Varnish Cache
Varnish 公式サイトです。 -
The Varnish Book
Varnish Software が提供しているガイドブックです。アーキテクチャからコマンドラインツール、設定パラメータ、VCLなど幅広い情報があります。 -
Varnish best practices
タイトルどおり Varnish のベストプラクティスです。VCL はシンプルに。 -
Upgrading from Varnish 2.1 to 3.0
ネット上には 2.x の情報が多いので、差分を確認。 -
Tuning — The Varnish Book
チューニングについて。 -
Varnish » cat /dev/random > /dev/null &
日本語で Varnish の情報を発信されている @xcir さんの blog です。ありがたや。
さいごに
Varnish は、手軽に導入できるわりに簡単にパフォーマンスを向上させることができます。とくに CMS のような閲覧が中心となるアプリケーションには大きな効果を発揮します。
CMS 自体にもキャッシュ機構などは付いていますが、それよりの上位でキャッシュできるので、バックエンドが負荷に耐えられない構成でもうまく吸収することができます。
個人的には VCL がプログラムっぽく書けるのが設定しやすくて好きです。
アクセス過多でパフォーマンスに問題が出た際に使える切り札として覚えておくと、いつか役立つ日が来るやもしれません。
公式サイトのドキュメントが英語なので、日本語でのまとまった情報があればと思うのですが、詳しい方(チラチラッ、Kindle とかでどうでしょうか 😀
おまけ Vagrantfile
簡単に Varnish を試せるように Vagrantfile を作りました。
vagrant up して、http://192.168.33.50/sample.php にアクセスすると現在日時が表示されます。こちらがバックエンドアプリケーションの想定ですので、リロードする度に表示される日時は変わっていきます。
Varnish は 6081 port で待ち受けているので、http://192.168.33.50:6081/sample.php にアクセスするとその時点でのページがキャッシュされます。リロードするとキャッシュが返され、日時が変更されていないことが分かるでしょう。
$ git clone https://github.com/shin1x1/vagrant-varnish $ vagrant up
- Newer: CentOS 6.5 に Docker をインストールしてみた
- Older: 書きかけの blog が延々と溜まっていく6つの理由