lighttpd + FastCGI は mod_perl + Apache1.3 より1割ほど高速
巷で超高速 Web サーバとして話題になっている lighttpd を試してみました。lighttpd に関する日本語ドキュメントは非常に少なく、ちょっと込み入った設定ファイルの記述方法とかの解析に手間取りました。
lighttpd のコンセプトは、「セキュアで省メモリで高速に動作し、柔軟性もある」なのですが、「lighttpd 公式サイトのベンチマーク結果」や「UnknownPlace. - Catalyst ベンチ」で簡単な Catalyst - Hello.cgi のベンチマークが公開されているとおり、Apache 1系、Apache 2系よりも高速に動作するようです。特に static なページの処理は Apache の 2〜3 倍程度は高速に処理できるみたいです。
また注目すべき点として、Apache + mod_perl よりも lighttpd + FastCGI の方が1割程度は高速と言う点です。
結果、lighttpd を導入することで、「リバースプロキシを導入する際はmod_rpaf」で紹介しているように、mod_perl を効率的に動作させる解としての「pound + Apache1-mod_perl + Apache2」や「Apache2-mod_proxy + Aapche1-mod_perl」なんて事が不要となり、lighttpd 1つでOKなんてことになります。
と言うことで、インストールして lighttpd に移行すべくいろいろ設定中なのですが、幾つかつまずいた点があるので備忘録です。
FastCGI のインストール lighttpd で FastCGI を動作させるには、FastCGI 本体が必須です。
wget http://www.fastcgi.com/dist/fcgi.tar.gz
tar xvfz fcgi-2.4.0.tar.gz
cd fcgi-2.4.0
./configure
make
make check
make install
perl -MCPAN -e 'install FCGI'
perl -MCPAN -e 'install CGI::Fast'
libpcre (Perl Compatible Regular Expressions)のインストール lighttpd で mod_rewrite 等を動作させるには、libpcre (正規表現ライブラリ)が必須です。
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-6.4.tar.gz
tar xvfz pcre-6.4.tar.gz
cd pcre-6.4
./configure
make
make install
PHP のインストール lighttpd で PHP を FastCGI として使う場合は、--enable-fastcgi オプションが必須。
wget http://jp.php.net/get/php-5.0.5.tar.gz/from/this/mirror
tar xvfz php-5.0.5.tar.gz
cd php-5.0.5
./configure \
--enable-fastcgi \
--enable-discard-path \
--enable-force-cgi-redirect \
--enable-mbstring \
--enable-mbregex \
--enable-mbstr-enc-trans \
--enable-iconv \
--enable-trans-sid \
--with-pgsql=/usr/local/pgsql \
--with-mysql=/usr/local/mysql \
--with-zlib=/usr --with-zlib-dir=/usr
make
make test
make install
cronolog のインストール ログをローテートするために必須です。
wget http://cronolog.org/download/cronolog-1.6.2.tar.gz
tar xvfz cronolog-1.6.2.tar.gz
cd cronolog-1.6.2
./configure
make
make install
lighttpd のインストール
wget http://www.lighttpd.net/download/lighttpd-1.4.4.tar.gz
tar xvfz lighttpd-1.4.4.tar.gz
cd lighttpd-1.4.4
./configure
make
make install
ln -s /usr/local/sbin/lighttpd /usr/sbin/lighttpd
以上で、lighttpd + FastCGI (perl) を使う下準備ができあがります。
次に、lighttpd の設定です。まず始めに lighttpd の自動起動と設定ファイルのテンプレートをコピーします。
cd lighttpd-1.4.4
cp doc/rc.lighttpd.redhat /etc/init.d/lighttpd
cp doc/lighttpd.conf /usr/local/etc/
/etc/init.d/lighttpd の設定 デフォルトの 起動ファイルを下記のように 25行目を変更します。
25c25
%lt; LIGHTTPD_CONF_PATH="/etc/lighttpd/lighttpd.conf"
---
> LIGHTTPD_CONF_PATH="/usr/local/etc/lighttpd.conf"
/usr/local/etc/lighttpd.conf の設定 ココはご自分の Apache の httpd.conf を参考に設定します。httpd.conf とは記述方法がかなり異なるので、設定ファイルのドキュメントや lighttpd の wiki を良く読みながら設定していきます。主立った設定ポイントとしては下記の通り。
- server.modules
- 使いたいモジュールを指定する。モジュールの名前は Apache と同じなので理解はし易いですね。
server.modules = (
"mod_rewrite",
"mod_access",
"mod_auth",
"mod_setenv",
"mod_fastcgi",
"mod_simple_vhost",
"mod_cgi",
"mod_accesslog" ) - server.document-root
- Apache で言うところの DocumentRoot です。
server.document-root = "/usr/local/apache/htdocs/"
- server.errorlog
- Apache で言うところの ErrorLog です。エラーログのファイル名を指定します。
server.errorlog = "/usr/local/apache/logs/error_log_L"
- accesslog.filename
- Apache で言うところの CustomLog です。アクセスログのファイル名を指定します。
accesslog.filename = "/usr/local/apache/logs/access_log_L"
- accesslog.format
- Apache で言うところの LogFormat です。パラメータも互換があるので Apache の設定をそのまま使えます。
accesslog.format = "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
- index-file.names
- Apache で言うところの DirectoryIndex です。ファイル名を指定しなかったときに、記述順にファイル名を補完してくれます。
index-file.names = ( "index.html", "index.htm", "index.cgi", "index.php" )
- mimetype.assign
- Apache で言うところの TypesConfig です。必要な mime の設定を行います。
mimetype.assign = (
".pdf" => "application/pdf",
〜中略〜
".tar.bz2" => "application/x-bzip-compressed-tar" ) - server.port
- Apache で言うところの Port です。通常 80 の指定で問題ないかと。
server.port = 8003
- server.username / server.groupname
- Apache で言うところの User / Group です。lighttpd を動作させる user / group を指定します。
server.username = "apache"
server.groupname = "apache" - cgi.assign
- Apache で言うところの AddHandler cgi-script みたいなモノです。拡張子と対応するエンジンを指定します。
cgi.assign = ( ".pl" => "/usr/bin/perl",
".cgi" => "/usr/bin/perl" ) - server.error-handler-404
- Apache で言うところの ErrorDocument 404 です。現時点では 404 以外のエラーに対して特別な html を指定することができないようです。
server.error-handler-404 = "/404.html"
- auth.backend.htpasswd.userfile
- Apache で言うところの .htpassword です。
auth.backend.htpasswd.userfile = "/usr/local/apache/htdocs/auth/.htpasswd"
- auth.require
- Apache で言うところの .htaccess に記述する認証設定です。記述方法が違うので戸惑うかも。
auth.require = ("/auth/" => (
"method" => "basic",
"realm" => "auth require pages",
"require" => "valid-user"
)
) - fastcgi.server
- Apache で言うところの FastCgiConfig に相当するモノです。記述方法が違うので戸惑うかも。fastcgi.server の設定は通常 dispatcher cgi を指定します。従って、一般的な設定は下記の通りとなります。
fastcgi.server = ( ".fcgi" =>
dispatch.fcgi のソースは例えばこんな感じのモノを参考に wiki にあります。
(( "socket" => "/tmp/application.fcgi.socket",
"bin-path" => "/usr/local/apache/scripts/dispatch.fcgi",
"min-procs" => 10,
"max-procs" => 20,
"idle-timeout" => 20
))
)
#!/usr/bin/perl
use strict;
use CGI::Fast;
use Embed::Persistent;
{
my $p = Embed::Persistent->new();
while (new CGI::Fast) {
my $filename = $ENV{SCRIPT_FILENAME};
my $package = $p->valid_package_name($filename);
my $mtime;
if ($p->cached($filename, $package, \$mtime)) {
eval {$package->handler;};
} else {
$p->eval_file($ENV{SCRIPT_FILENAME});
}
}
}ただ、これだと特定の FastCGI プロセス数を管理できないので、下記のように個別に設定すると良い感じ。
fastcgi.server = (
"/test1.fcgi" => (
"test1" => (
"socket" => "/tmp/fastcgi_test1.socket",
"bin-path" => "/usr/local/apache/scripts/test1.fcgi",
"min-procs" => 1,
"max-procs" => 1,
"idle-timeout" => 20
)
),
"/test2.fcgi" => (
"test2" => (
"socket" => "/tmp/fastcgi_test2.socket",
"bin-path" => "/usr/local/apache/scripts/test2.fcgi",
"min-procs" => 2,
"max-procs" => 3,
"idle-timeout" => 20
)
)
) - $HTTP["host"]
- Apache で言うところの VirtualHost に相当するモノです。全てのパラメータは VirtualHost 毎に個別に設定可能です。
$HTTP["host"] == "www.drk7.jp" {
server.document-root= "/home/apache/drk7.jp"
server.name = "www.drk7.jp"
accesslog.format = "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
accesslog.filename = "|/usr/local/sbin/cronolog /home/apache/drk7.jp/logs/access_log_L.%Y%m%d"
server.errorlog = "/home/apache/drk7.jp/logs/error_log_L"}
最後に簡単な CGI でベンチマークを図ってみました。ウワサ通り、mod_perl より1割程度高速な結果が出ました。
mod_perl サンプル CGI のソース
#!/usr/bin/perl
use strict;
use CGI;
our %count;
&_process_request(CGI->new);
sub _process_request() {
my $q = shift;
my $procid = $q->param('pid');
$count{$procid} += 1;
print $q->header( -type=>'text/html',-charset=>'EUC-JP' );
print qq{
FastCGI Hello! (Perl)
FastCGI Hello! (Perl)
ProcID : $$ : $procid
Request number : $count{$procid}
};
}
FastCGI サンプル CGI のソース
#!/usr/bin/perl
use strict;
use CGI::Fast;
our %count;
while (my $q = CGI::Fast->new) {
&_process_request($q);
}
sub _process_request() {
my $q = shift;
my $procid = $q->param('pid');
$count{$procid} += 1;
print $q->header( -type=>'text/html',-charset=>'EUC-JP' );
print qq{
FastCGI Hello! (Perl)
FastCGI Hello! (Perl)
ProcID : $$ : $procid
Request number : $count{$procid}
};
}
ベンチマーク結果
Requests per second: 740.74 [#/sec] (mean)
Time per request: 13.50 [ms] (mean)
Time per request: 1.35 [ms] (mean, across all concurrent requests)
Transfer rate: 217.52 [Kbytes/sec] received
Requests per second: 862.07 [#/sec] (mean)
Time per request: 11.60 [ms] (mean)
Time per request: 1.16 [ms] (mean, across all concurrent requests)
Transfer rate: 246.48 [Kbytes/sec] received
さぁ、興味がわいた方は Apache から lighttpd へ移行してみよう!
コメントやシェアをお願いします!
drk
Craftworks さん> server.errorlogの件はご指摘の通りです。
VirtualHost 毎に個別に設定可能ですの部分にserver.errorlogの設定が入っているのは間違いですね。
ご指摘有り難うございます。
Craftworks
server.errorlog はひとつしか設定できません。conf の中で一番最後に記述されたものが適用されます。lighttpd のバグか知りませんが。
drk
ボンヌさん> mod_perl と FastCGI の差と言うよりは Apache と lighttpd の差と言った方が正確と思います。mod_perl 派な僕としても mod_perl を否定するつもりは全くなくて、単に lighttpd + mod_perl が使えないのでって感じかも。
ボンヌ
はじめまして、ボンヌと申します。
いつも詳細な内容で、参考にさせていただいております。
一点疑問があるのですが・・・
Apache1+mod_perlでは基本的にモジュールをロードしてオンメモリの状態に
することで、それ以降のリクエストを大幅に短縮していると思うのですが。。。
lightTPDである程度規模の大きいアプリ(およびフレームワーク)を実行した場合、
mod_perlと比較して処理速度はどのように変わるのでしょうか。
例としてはSledge+各種Pluginなど。
(って聞くだけじゃダメですね!こっちでも色々やってみないと。)
よろしければ、ご意見いただければ幸いです。
以上、失礼いたしました!!