Web サーバーのチューニング
全世界的に、Web サーバーとしては Apache が一番多く使われています。その Apache を利用する際になるべく最適な環境を作る方法についてまとめてみます。
1. はじめに
Apache の設定ファイルは、httpd.conf、srm.conf、 access.conf と三種類ありますが、最近のバージョンではほとんど httpd.conf のみで行います。Apache 2.0 では、srm.conf, access.conf は無くなります。そこで、設定はすべて httpd.conf で行なうものと思って作業してください。
2. Apache のチューニング(httpd)
Apache は、デフォルトで運営上必要のない機能をインストールしてしまうときがあります。これらを、取り除くことでスマートなサーバーを構築することができます。Apache では、ここの機能をモジュール化して管理しています。
Apache をコンパイルする方法は、以下のようになります。
# ./configure # make # make install
この、configure
を実行する際に、不要なモジュールを無効にすることでスマートなサーバーを作ります。モジュールを有効にするかどうかは、以下のコマンドラインオプションを利用します。モジュール(mod_
)は数多くあるので、ドキュメントを参照してください。
コマンドラインオプション |
説明 |
--enable-MODULE[=shared] |
モジュールMODULE をコンパイルして機能として組み込みます。MODULE には、ドキュメントに記載されているモジュール名から "mod_ " または "_module " を取り除いた文字列です(mod_expires の場合 expires となる)。 DSO (Dynamic Shared Object) としてモジュールをコンパイルする場合は、
=shared オプションを付加してください。./configure --enable-expires |
--disable-MODULE |
デフォルトで組み込まれるモジュールを取り除きたいときに使用します。また、すべてのモジュールを組み込んで、いくつか取り除きたいときなどにも利用します。./configure --enable-mods-shared=all --disable-info |
--enable-modules=MODULE-LIST |
複数のモジュールを組み込みたいときに、スペースで区切ってリストします。./configure --enable-modules="speling info" |
--enable-mods-shared=MODULE-LIST |
複数のモジュールをDSOできるモジュールとして組み込みたいときに、スペースで区切ってリストします。 |
Web アプリケーションを動作させる環境を構築する際に、一般のユーザーが個人のページのサーバーとして利用することはあまり考えられないので mod_userdir のような機能は取り除かれることがあります。
3. Apache のチューニング(httpd.conf)
設定ファイルでは、幾つかディレクティブがあります。その中で注意して設定することで、Apache を最適に動作させるディレクティブ説明と方法を記述します。
3.1. HostnameLookups
HostnameLookups は、Web サーバーである Apache にアクセスしてきたクライアント(ブラウザを利用しているPCなど)の情報をアクセスログに記録する際に IP Address で記録するか ホスト名で記録するかを設定します。on と設定することで、IP Address から DNS でホスト名を逆引きしてアクセスログに記録します。off の場合、そのまま IP Address で記録します。この時、やはりアクセスログはホスト名で記録されている方が分かりやすいので on に設定しがちです。しかし、DNS による逆引きはシステムに負荷をかけます。そこで、ログファイルを解析する際に重視するファイルに対してのみに対して逆引きをするように設定します。例は、.html と .cgi のアクセスだけ DNS による逆引きを行ないます。
HostnameLookups off <Files ~ "\.(html|cgi)$"> HostnameLookups on </Files>
HostnameLookups を off にしておき、ログファイルを参照する時に logresolve コマンドで DNS による逆引きを行う方法もあります。
3.2. DirectoryIndex
ディレクトリに対する(末尾が「/」で終わる URL への)アクセスがあった場合に、 実際のディレクトリの中身の一覧の代わりに 転送するファイルのファイル名を設定します(デフォルトは index.html
)。この事を、コンテンツ・ネゴシエーションといいます。もし、Web サーバーに最高のパフォーマンスを要求するなら、このネゴシエーション機能を無効にすることですが、ある程度機能低下を伴っても利用する利点はあります。その中で、なるべく
Web サーバーに負荷をかけないようにするには、
DirectoryIndex index
という具合にワイルドカードを利用するのではなく
DirectoryIndex index.html index.shtml index.cgi
と全て羅列することです。一番頻繁に使うものをリストの先頭に記述する。本当なら、index.html のみの方がよい。
3.3. AllowOverride
アクセス権の設定を、AccessFileName
で指定したファイル(.htaccess)の内容によって上書きできる属性を指定します。セキュリティの観点などから一切上書きを許可しない場合には None
を設定します。しかし、どうしても上書きを許可したい場所がでてきた場合、許可するパス以降に対してのみ設定するようにして下さい。例えば、
DocumentRoot /home/httpd/html <Directory /> AllowOverride All </Directory>
として /index.html の URI をリクエストをした場合、Web サーバーは /.htaccess, /home/.htaccess, /home/httpd/.htacsess, /home/httpd/html/.htaccess を開こうとします。このようなことが無いように AllowOverride を指定しなければならなくなった場合は以下のように明確に指定する。
DocumentRoot /home/httpd/html <Directory /> AllowOverride none </Directory> <Directory /home/httpd/html> AllowOverride All </Directory>
パフォーマンスを追求するなら、どんなところでも AllowOverride None とすることをお勧めします。
3.4. Option の FollowSymLinks と SymLinksIfOwnerMatch
シンボリックリンク先の参照を許可する FollowSymLinks は、シンボリック先を参照するのは安全性に問題があるので利用しない方が良いと考えます。しかし、ファイルやディレクトリーがシンボリックされているかどうかチェックするためにそれぞれのファイルやディレクトリーに対して lstat 関数を実行します。さらに、lstat の結果はキャッシュされないのでリクエストのたびに発生します。これは、パフォーマンスを考えると非常に問題になります。また、シンボリックリンクファイルの持ち主とリンク先ファイル/ディレクトリの持ち主が同じだった場合にリンク先を参照することを許可する SymLinksIfOwnerMatch は、設定されるとパフォーマンスに影響します。でも、どうしてもセキュリティーチェックが必要なら以下のような設定をお勧めします。
DocumentRoot /home/httpd/html <Directory /> Options FollowSymLinks </Directory> <Directory /home/httpd/html> Options -FollowSymLinks +SymLinksIfOwnerMatch </Directory>
このように設定することで、少なくとも DocumentRoot までの余分なパスのチェックが要らなくなります。Alias や RewriteRule で設定したパスに対しても同様な処理をする必要があります。最高のパフォーマンスを引き出すには、全ての箇所に FollowSymLinks を設定し、SymLinksIfOwnerMatch を絶対に設定しないことです。
3.5. プロセスに関するディレクティブ
MaxSpareServers
, MinSpareServers
, StartServers
を運用する目的に適した値に設定することで、パフォーマンスを最適に設定することができます。
StartServers
Apache の起動時にいくつの分身サーバを作成するかを設定します。
MaxSpareServers
リクエスト待ち状態のサーバプロセスが、最大いくつまでいてもよいかを設定します。 メインの Apache はリクエスト待ち状態のサーバプロセスが
ここで設定した数よりも多くなると、余ったサーバを適宜終了させます。アプリケーションサーバーなどを構築して運用する場合、システムの CPU
やメモリを増設しても、この値を適切な値に設定しないとパフォーマンス強化の効果が得られないので注意してください。
MinSpareServers
リクエスト待ち状態のサーバプロセスが、最小いくついなくてはならないかを設定します。 メインの Apache はリクエスト待ち状態のサーバプロセスが、ここで設定した数よりも少なくなると適宜必要な数だけ分身のサーバを生成します。
Apache 1.3 以降では、子プロセスを1つ発生させ1秒待ち、2つ発生させ1秒待ち、4つ発生させ1秒待ちという要領で1秒あたりの子プロセスを32発生させるまで乗数的に続きます。(MinSpareServers を満たした時点で止まる)これだけのレスポンスがあればデフォルトの設定をいじらなくても大丈夫かも知れませんが、1秒間に4つ以上の子プロセスが発生すると ErrorLog にメッセージが記録されます。このメッセージが頻繁に発生するようになったら上記3つの設定を変えることを検討すると良いでしょう。
MaxRequestsPerChild
によって子プロセスの消滅を指定できます。指定したリクエストを処理すると消滅することで、プロセスが肥大化するのを防ぐ目的で使用されます。初期値が
30 となっていますが、ページが静的なものであれば 10,000 ぐらいまで上げても問題にはならない(もっと上げても大丈夫)。mod_perl
などを利用する際は調査が必要です。
MaxClients
によって、サーバーが同時にアクセスを受け付けられるクライアント数の最大値を設定します。この設定は、MaxRequestsPerChild
の値と MaxSpareServers
, MinSpareServers
, StartServers
の値等を考慮して設定するとよい。
keep-alives が使われている場合、既に開かれている接続により子プロセスが何もしない状態で次のリクエストを待っている。KeepAliveTimeout
の設定は、この待ち時間を設定するものだが 60秒以上にしてはいけない。
3.6. セキュリティーに関するディレクティブ
以下で説明するディレクティブを利用して、ほんの気持ち程度セキュリティーを強化することができます。
- バージョンが知られることによる、クラックを防ぐためにServerTokens, ServerSignature を以下のように設定するとよい。
ServerTokens ProductOnly ServerSignature Off
- DirectoryIndex で指定したファイル(大抵は index.html)が存在しない場合、ディレクトリ内がリストされてしまうことがある。これを、内容がリストされずにエラーにするには以下のように Indexes を無効にするとよい。デフォルトで以下のように設定されている場合が多い。
<Directory "/usr/local/apache/htdocs"> Options -Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny Allow from all </Directory>
- エラー発生時に表示されるページをカスタマイズしたい場合、エラー番号に対応したページを作成し指定することで実現できます。
ErrorDocument 400 /error/bad.html ErrorDocument 401 /error/auth.html ErrorDocument 403 /error/forbidden.html ErrorDocument 404 /error/missing.html ErrorDocument 500 /error/server.html
- 特定のユーザーのみアクセスを許可する方法。はじめの Directoryディレクティブで指定されたディレクトリーは、指定のIPアドレスを持つクライアントのみアクセスが許可される。2番目のDirectoryディレクティブに書かれたディレクトリーは、.htpasswd に登録されたユーザーがパスワードによる認証が成功したときにのみアクセスが許可されます。.htpasswd にユーザーを登録するには、htpasswdコマンドを使用します。AllowOverrideディレクティブの設定によっては、Directoryディレクティブの内容を .htaccess ファイルで置き換えることができます。
<Directory "/usr/local/apache/htdocs/admin"> Options ExecCGI -FollowSymLinks AllowOverride All Order deny,allow Deny from All Allow from 192.168.0.1 192.168.0.2 </Directory> <Directory "/usr/local/apache/htdocs/admin2"> AuthType Basic AuthName "Please enter username and password" AuthUserFile /usr/local/apache/htdocs/.htpasswd AuthGroupFile /dev/null <Limit GET POST> require valid-user </Limit> </Directory>
- 上記で設定したファイルなど、特定のファイルのアクセスを拒否させるには以下のように設定します。(例では、.ht で始まるファイル)デフォルトで以下のように設定されている場合が多い。
<Files ~ "^\.ht"> Order allow,deny Deny from all </Files>
- クラックプログラムなどで不正アクセスをされるのを防ぐために、きちんとしたブラウザからのみアクセスを許可するといった設定をします。以下の設定では、Internet Explorer, Netscape, Opera, Safari など主要なブラウザからはアクセスすることが可能になります。おまけで、google からも許可しよう。(しかし、ブラウザーの情報は簡単に偽装できてしまいます)
SetEnvIf User-Agent "Mozilla" AllowedBrowser SetEnvIf User-Agent "GoogleBot" AllowedBrowser <Files *> Order deny,allow Deny from all Allow from env=AllowedBrowser </Files>
3.7. 文字設定に関するディレクティブ(Apache 2.0 では必要?)
Apache 2.0 では、各 Webページで以下のように META タグによって charaset を指定していても
<META http-equiv=Content-Type content="text/html; charset=Shift_JIS">
デフォルトの設定で ISO-8859-1(ラテン系欧州語、フランス語、ドイツ語)文字セットを補うようになっています。そこで、 DefaultLanguage
, AddDefaultCharset
, LanguagePriority
をきちんと設定して Webサイトに合う文字設定を行う必要があります。
# DefaultLanguage nl # デフォルト言語を ja にする DefaultLanguage ja #LanguagePriority en da nl et fr de el it ja kr no pl pt pt-br ltz ca es sv tw # リストのオーダーを ja を先頭にする LanguagePriority ja en da nl et fr de el it kr no pl pt pt-br ltz ca es sv tw # AddDefaultCharset ISO-8859-1 コメントアウト # AddDefaultCharset EUC-JP または、ISO-2022-JP, EUC-JP, shift_jis に設定
4. Linux のチューニング
4.1. ファイルディスクプリタ
Web サーバーマシンとして Linux を利用する場合、システムが一度にオープンできる最大ファイル数と最大 i-node 数を増やしておくと良い(バージョン 2.2 カーネルで、デフォルトの4倍ぐらいが推奨値)。システムの起動スクリプトに、以下の行を追加することで Web サーバーが可能な限り多くのシステムリソースを使用できるようにする。
echo 16384 > /proc/sys/fs/file-max echo 49152 > /proc/sys/fs/inode-max
Linux の /proc ファイルシステムは、ユーザーとカーネルのインターフェースを提供します。ユーザーは、幾つかの読み込み専用のファイルを参照することで、カーネルの利用率に関する統計情報を確認できます。top, vmstat というコマンドを利用すれば、それら統計情報を取得して表示してくれます。
4.2. プロセス
Linux の 2.2 カーネルでは、1ユーザー当たり 256 プロセスという制限があるのでスレッドの作成が制限される場合があります。これを変更するには、/usr/src/linux/include/linux/tasks.h の NR_TASKS, MAX_TASKS_PER_USER を修正する必要があります。
/usr/src/linux/include/linux/tasks.h | #define NR_TASKS 1024 #define MAX_TASKS_PER_USER (NR_TASKS-256)
|
修正後、カーネルを再構築します。カーネル 2.2.14 では、デフォルトで 2048 になっています。
4.3. 物理メモリ
Linux は、デフォルトで 1GB 以上のメモリが載っていても、1GB までしか使用しません。(1GB の一部は除外され、実際には 950MB )もし、2GB のメモリを載せているなら、メッセージングパフォーマンスが強化される可能性があります。それには、/usr/src/linux/include/asm-i386/page.h と /usr/src/linux/arch/i386/vmlinux.lds を修正する必要があります。このメモリ制限の拡張によって、動作しなくなるもの(boot ramdisk 等)があります。
1GB 0xC0000000/ 2GB 0x80000000/ 3GB 0x40000000
|
|
/usr/src/linux/include/asm-i386/page.h | #define _PAGE_OFFSET (0x80000000)
|
/usr/src/linux/arch/i386/vmlinux.lds | .=0x80000000 + 0x100000;
|
修正後、カーネルを再構築します。カーネル 2.2.14 では、ソースを編集しなくても、カーネルコンフィグレーション(make menuconfig 等)の "Processor type and features" の "Maximum Physical Memory" で設定できます。
4.4. ファイル情報の更新
Linux は、デフォルトでファイルの読み込みごとにアクセスタイムをディスクに書き込みます。もし、単なるファイルの読み込みに対するアクセスタイムの情報が必要ないのなら noatime オプションによって余計なディスク書き込みを回避することが出来ます。それには、/etc/fstab を以下のように修正します。アクセス時刻情報を必要とする
/etc/fstab | /dev/sda6 /disk ext2 defaults,noatime 1 2
|
4.5. スワップサイズと高速化
意外と、スワップについてあまり意識しない方が多いのでは無いでしょうか?確かに Linux システムは、スワップサイズの設定(デフォルトスワップ・サイズ:128 ランナウェイ・プロセス、クライアント側から故意に不正な処理を行いサーバーの過負荷を引き起こすサービス拒否アタック、短時間に多くのクライアントの要求が殺到するスラッシュドット効果などにたえなければなりません。これには、高速なスワップを適切に設定しなければ、物理メモリーを使い尽くしてサーバーが停止またはクラッシュしてしまいます。
Linux 2.2 以降のカーネルでは、スワップサイズが 128 MB という制限はなくなったので、スワップに多くの領域を割り当てられるようになりました。(現在は、x86系の CPU で約 2 GB)でも、パフォーマンス改善は?確かに、領域が増えてもパフォーマンスの改善はみられません。この改善の方法として、複数のスワップ・パーティションを RAID 0(ストライピング)に設定し、すべてのパーティション間で読み書きを均一に分散すると効率的です。もし、これらのパーティションが別 々のドライブや制御装置にあると、サーバーはメモリー使用率の "スパイク" (瞬間的急上昇) をすばやく処理できるようになり、スワップ・ファイルのパフォーマンスが格段に向上します。 スワップにそんな贅沢な設定ができるか!とお叱りを受けそうですが、なんと最新の Linux カーネルでは、デフォルトで RAID 0 のようにスワップを並列化することができます。それには、/etc/fstab でスワップパーティションを複数指定する際に、pri オプションを使って優先度を同じに設定することで、スワップパーティションを並列に使用するようになります。
複数のスワップ・パーティションを同じ優先度する方法 (/etc/fstab)
/dev/sda2 none swap sw,pri=5 0 0 /dev/sdb2 none swap sw,pri=5 0 0 /dev/sdc2 none swap sw,pri=2 0 0
上記のように設定すると、スワップ・パーティションである sda2 と sdb2 を並列に使用するようになります。これらのパーティションはそれぞれ別のドライブなので、読み書きのスループットがほぼ 2倍に向上します。3番目のスワップ・パーティションである sdc2 は、優先度が低いので最初の 2つのパーティションがいっぱいになった時にのみ使用されます。
pri オプションの優先度の指定は、0 から 32767 までの間の数値で指定します (32767 が最高の優先度)。それぞれのスワップ・パーティションは、優先度の高い順に使用されます。つまり、優先度の低いパーティションは、優先度の高いパーティションがいっぱいになった場合にのみ使用されます。いくつかのパーティションの優先度が同じであれば、自動的にそれらのパーティションに並列にアクセスします。この優先度を設定する方法は並列化でなくても、最も高速なドライブを常に使用されるスワップ・パーティションとして優先度を設定し、非常用スワップ・パーティションとして低速なドライブを指定するといった設定をすることもできます。
5. FreeBSD のチューニング
5.1 プロセス
FreeBSD 4.X または FreeBSD 6.X以降の32bitアプリケーションでは、1プロセスあたりのメモリ使用量が 512MBに制限されている。せっかく多くのメモリを搭載しても利用されないので変更する必要があります。(64bit アプリケーションは制限がありません)
FreeBSD 4.Xの場合、/boot/defaults/loader.conf.local (/boot/loader.conf)に以下の設定をしてOSを再起動する。
kern.maxdsiz="1073741824" # 1G
FreeBSD 6.X 32bitアプリに対しての設定の場合、/boot/loader.conf.local (/boot/loader.conf)に以下の設定をしてOSを再起動する。
compat.ia32.maxdsiz="1073741824" # 1G
※ sysctlコマンドで、動的に設定できるが OS を再起動するとデフォルトに戻ってしまうので設定ファイルに追記しておく方が良い
5.2 TCP コネクションの数
利用者数が多い場合、listen キューの数を増やすと良い。/etc/sysctl.conf.local (/etc/sysctl.conf)に以下の設定をしてOSを再起動する。
kern.ipc.somaxconn=4096