«前の日記(2011-05-04(Wed)) 最新 次の日記(2011-05-06(Fri))» 編集
RSS feed

ぽっぺん日記@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動かしています(キリッ」ってドヤ顔できるくらい。

参考リンク

_ [日常]GW5日目

昨日の祖母の墓参りにつづき、今日は妻方の叔母の墓参り。

普段はなかなか時間がなくて墓参りには行けないので、連休くらいは先立った人に時間を使うのもいいかなーと。ドライブみたいなもんだし。

叔母の墓では初めてキリスト教会の墓を見た。賛美歌(?)を歌っている人たちがいて心が和んだ。


«前の日記(2011-05-04(Wed)) 最新 次の日記(2011-05-06(Fri))» 編集
RSS feed