ぽっぺん日記@karashi.org
2011-05-05(Thu) こどもの日 [長年日記]
_ [tDiary]tDiary を Ruby Enterprise Edition(1.8.7) + nginx + fcgi で動かしてみた
最近、仕事で使うhttpdサーバがnginxばかりなってきたので、ligttpdで動かしているtDiaryもnginxで動かしてみることにした。
結果から書いておくと、かなりめんどくさくて、あまりオススメできない。あくまでもnginx大好きな人向け。
設定と日記の書き方については、tDiary を ruby1.9 + nginx + fcgi で動かしてみた - まちゅダイアリー(2010-04-29)を参考にさせていただきました。
履歴
- 2011.05.05:初版
- 2011.05.06:Rubyのfcgiモジュールについて追記。その他、細かいところを手直し
- 2011.05.29:Nginx Pitfallsを参考に、nginxの設定の間違いを訂正
環境
- Ubutu 10.04 LTS 32bit
- nginx 1.0.0
- ruby Enterprise Edition 1.8.7-p334
- tDiary 3.0.2
Ruby Enterprise Editionのインストール
Ruby Enterprise Editionを使うと、メモリ消費が抑えられるので、いつも使っている。いいんです、Ruby 1.8で!
Ubutuなので、debパッケージを使用。
% wget http://rubyenterpriseedition.googlecode.com/files/ruby-enterprise_1.8.7-2011.03_i386_ubuntu10.04.deb % dpkg -i ruby-enterprise_1.8.7-2011.03_i386_ubuntu10.04.deb
nginxのインストール
Ruby EEにはPassengerがバンドルしてあるので、せっかくなので、passenger-installでnginxをインストールしてしまう。
♯ ってよく考えたら、passengerのgemをupdateしているので、「せっかく」もなにもあったもんじゃないw
% sudo /usr/local/bin/gem update passenger % sudo apt-get install g++ libssl-dev zlib1g-dev libcurl4-openssl-dev % wget http://nginx.org/download/nginx-1.0.0.tar.gz % tar xzf nginx-1.0.0.tar.gz % sudo /usr/local/lib/ruby/gems/1.8/gems/passenger-3.0.7/bin/passenger-install-nginx-module
途中でnginxのソースの場所が聞かれるので、/path/to/nginx-1.0.0 を入力する。インストール場所など聞かれるので、そちらはお好みで。
nginxのinitスクリプトは、Ubutuのnginx debパッケージのものにちょっとだけ手を入れて使っている。
/etc/init.d/nginx
#! /bin/sh
### BEGIN INIT INFO
# Provides: nginx
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the nginx web server
# Description: starts nginx using start-stop-daemon
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/nginx
NAME=nginx
DESC=nginx
test -x $DAEMON || exit 0
# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then
. /etc/default/nginx
fi
set -e
. /lib/lsb/init-functions
test_nginx_config() {
if $DAEMON -t $DAEMON_OPTS
then
return 0
else
return $?
fi
}
case "$1" in
start)
echo -n "Starting $DESC: "
test_nginx_config
start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \
--exec $DAEMON -- $DAEMON_OPTS || true
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \
--exec $DAEMON || true
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $DESC: "
start-stop-daemon --stop --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON || true
sleep 1
test_nginx_config
start-stop-daemon --start --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS || true
echo "$NAME."
;;
reload)
echo -n "Reloading $DESC configuration: "
test_nginx_config
start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/$NAME.pid \
--exec $DAEMON || true
echo "$NAME."
;;
configtest)
echo -n "Testing $DESC configuration: "
if test_nginx_config
then
echo "$NAME."
else
exit $?
fi
;;
status)
status_of_proc -p /var/run/$NAME.pid "$DAEMON" nginx && exit 0 || exit $?
;;
*)
echo "Usage: $NAME {start|stop|restart|reload|force-reload|status|configtest}" >&2
exit 1
;;
esac
exit 0
passenger-installの標準ディレクトリを使った場合は、ホスト用の設定ファイルも書いておく。
/etc/default/nginx
DAEMON=/opt/nginx/sbin/nginx DAEMON_OPTS="-c /etc/nginx/nginx.conf"
nginxを再起動しておく。
% sudo service nginx restart
spawn-fcgiのインストール
nginxはfastcgi経由でしかcgiを呼び出すことしかできないので、spawn-fcgiが必要。
% sudo apt-get install spawn-fcgi
Rubyのfcgi環境の構築
Rubyにfcgiのモジュールをインストールする。
% sudo apt-get install libfcgi-dev % sudo /usr/local/bin/gem install fcgi
fcgiwrapのインストール
fcgiwrapは、その名と通り、cgiをwrapしてfcgiにしてくれる。
Ubutu 10.04にはfcgiwrapのパッケージがないので、nginxとfcgiwrapでcgiを動かす(Ubuntu 10.04、10.10対応) - odawaraの「はてな de メモ」を参考に、新しいバージョンのパッケージをもらってくる。
% wget http://ftp.jaist.ac.jp/pub/Linux/ubuntu/pool/universe/f/fcgiwrap/fcgiwrap_1.0.3-3_i386.deb % sudo dpkg -i fcgiwrap_1.0.3-3_i386.deb
なんとなくUnix socketよりIPv4 socketが好みなので、ホスト用の設定ファイルを書いておく。
/etc/default/fcgiwrap
FCGI_ADDR=127.0.0.1 FCGI_PORT=8000 FCGI_CHILDREN="8" FCGI_SOCKET=
FCGI_CHILDRENはプロセス数なので、お好みで。
daemontoolsのインストール
index.fcgiのプロセスの死活管理のために、daemontoolsを導入する。まぁ、実際のところはそんなに頻繁に死ぬものでもないと思うので、必要ないかもしれないけど、念のため。
% sudo apt-get install daemontools daemontools-run svtools
daemontoolsを有効にするために再起動する。
再起動後、/etc/serviceがdaemontoolsの管理ディレクトリになる。
index.fcgiの設定
% sudo mkdir -p /etc/service/tdiary
runスクリプトを作成する。
/etc/service/tdiary/run
#!/bin/sh exec setuidgid www-data /usr/bin/spawn-fcgi -n -a 127.0.0.1 -p 10003 -f /var/www/d.karashi.org/html/index.fcgi
オプションについては
% man spawn-fcgi
を参照のこと。
daemontools管理下で動くようにする。
sudo chmod +x /etc/service/tdiary/run
動作を確認する。
sudo svstat /etc/service/tdiary
nginxの設定
長いけど、引用しておく。
upstream tdiary {
server 127.0.0.1:10003;
}
upstream fcgiwrap {
service 127.0.0.1:8000;
}
#
# HTTP server
#
server {
server_name d.karashi.org;
root /var/www/d.karashi.org/html;
index index.fcgi;
#index index.rb; # for normal cgi
location / {
rewrite ^/(\d+)(-\d+)?\.html$ /?date=$1$2 last;
}
location ~ \.fcgi {
fastcgi_pass tdiary;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ^~ /update.rb {
auth_basic "Restricted";
auth_basic_user_file htpasswd;
fastcgi_pass fcgiwarp;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ \.rb {
fastcgi_pass fcgiwarp;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location /images/ {
alias /var/www/d.karashi.org/diary/images/;
}
location ~ /(.*\.rhtml|tdiary\..*|.*\.log\..*) {
deny all;
}
}
キモはlocation ^~ /update.rbのあたり。nginxのlocation設定はかなり独特なので、注意する必要がある。nginx - locationの文字列と正規表現の優先順位 - うまい棒blogが参考になる。
速度比較
% ab -n 100 -c 10
でベンチマークを取ってみた。
ligttpd
Requests per second: 3.26 [#/sec] (mean)
Time per request: 3069.199 [ms] (mean)
Time per request: 306.920 [ms] (mean, across all concurrent requests)
Transfer rate: 144.03 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 9 13 5.7 11 34
Processing: 2170 2958 626.5 3156 4753
Waiting: 2124 2889 614.2 3093 4445
Total: 2186 2971 627.6 3166 4787
nginx
Requests per second: 3.15 [#/sec] (mean)
Time per request: 3176.178 [ms] (mean)
Time per request: 317.618 [ms] (mean, across all concurrent requests)
Transfer rate: 139.16 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 10 13 4.3 11 36
Processing: 350 3027 515.0 3147 3457
Waiting: 314 2986 514.3 3109 3419
Total: 370 3039 512.9 3161 3468
当たり前ちゃ当たり前なんだけど、どっちもspawn-fcgi使っているんだから、誤差の範囲。
課題
- index.fcgiをforkして複数プロセスで動かすためにはmultiwatchが必要なので導入を検討する。ただし、Ubuntu 10.04にはパッケージがない。
- tDiaryを入れ替えた場合には svc -t /etc/service/tdiary する必要がある。
まとめ
最初に書いた通り、導入も、導入以後のプロセス管理もめんどくさいので、lighttpdからnginxへ移行するメリットはない。
無理矢理メリットを探すと、「nginxでtDiary動かしています(キリッ」ってドヤ顔できるくらい。
