nginxやvarnishなどがアツいですが、Apacheもまだまだ実績や安定性から採用されていると思います。ここではデフォルトとは異なる値に変更するサーバ設定を中心に、パフォーマンス改善、安全性向上のためのApacheの設定を紹介します。
mpmの確認
> /path/to/bin/httpd -V
Server version: Apache/2.2.19 (Unix)
Server built: Jun 23 2011 17:13:13
Server's Module Magic Number: 20051115:28
Server loaded: APR 1.4.5, APR-Util 1.3.12
Compiled using: APR 1.4.5, APR-Util 1.3.12
Architecture: 64-bit
Server MPM: Worker
PreforkやWorkerが使われます。Workerはマルチスレッドとマルチプロセスのハイブリッド型で、Preforkより少ないリソースで多くのレスポンスに応答することができます
プロセス/スレッドの設定
Timeout 300
Timeoutはリクエスト/レスポンスの送受信、CGIやProxy(ProxyTimeoutが指定されていない場合)のタイムアウトとして使われます。デフォルト300秒でとくに変更する理由はないでしょう
KeepAlive Off
MaxKeepAliveRequests 20
KeepAliveTimeout 1
クライアントとサーバ間のKeepAliveの設定です。画像配信など特定の目的専用のサーバでない限り、Offのほうが問題が少ないと考えています。Onにする場合は、MaxKeepAliveRequests(1つの接続で何回のリクエストに応えるか)、KeepAliveTimeout(送受信が終わった後何秒で接続を切るかの時間)の数値を大きくしすぎないようにしましょう。アクセスの多いサイトの場合、送受信が終わった後のidle接続が溜まり、MaxClientsに達してしまうなどパフォーマンスに影響がでる可能性があります
ServerLimit 64
ThreadLimit 32
StartServers 16
MaxClients 512
MinSpareThreads 512
MaxSpareThreads 512
ThreadsPerChild 32
Workerの場合は、MaxClientsとThreadPerChildによってプロセス数を制御します。上記の例では、MaxClientsが512、1プロセスあたりのスレッド数(ThreadsPerChild)が32なので、16プロセス立ち上がります。より大きなMaxClientsを指定したい場合は、ServerLimit(プロセス数の上限値)、ThreadLimit(スレッド数の上限値)を変更するといいでしょう。StartServersはプロセス数なので注意
もちろん、プロのサーバ管理者は、StartServers、MaxClients、(Min|Max)SpareThreadsが等しくなるように設定します
でも紹介しています。
MaxRequestsPerChild 5000
1スレッド(Preforkならプロセス)が受け付けるリクエスト数です。指定した値に達するとスレッド(プロセス)は終了し、新しいスレッド(プロセス)と入れ替わります。KeepAliveがOnの場合は、1つの接続が1リクエストとカウントされるので1スレッド(プロセス)が扱う最大接続数と同じ意味になります
hirose31さんのmod_bumpy_lifeを導入するとこのMaxRequestsPerChildにランダム性を取り入れることができます
MaxRequestsPerChildMin 4000
MaxRequestsPerChildMax 5000
このように指定することで、4000から5000の間でランダムにスレッドが終了します。これにより一斉にスレッドが終了し、一時的に負荷が高くなるような問題(Thundering Herd)を避けることができます。
サーバ動作の設定
ServerTokens Prod
ServerSignature Off
レスポンスのヘッダや、エラーページのフッタに Apache のバージョン等を表示するかの設定です。バージョンを隠すことにどれほどの意味があるのかは疑問ですが、表示しないようにするには、ServerTokensにProd(Apacheとだけ表示)、ServerSignature(フッタ)はOffにします。
TraceEnable off
TRACEメソッドは送ったリクエストの内容をそのまま返すHTTP/1.1で定義されているメソッドです。サイトにXSS脆弱性があった場合、XHRでTRACEメソッドを送り、Cookieなどの内容を読み出せる可能性があります。通常必要ないので、Offがお勧めです
RequestReadTimeout header=10 body=30
slowloris対策として導入されたmod_reqtimeoutの設定です。上の設定では、headerをすべて受信するのに10秒、bodyを受信するのに30秒の制限を設けています。
SetEnv proxy-nokeepalive 1
proxyの動作を制御する環境変数です。Apacheのmod_proxyはbackendとの接続を永続化することができますが、それを無効にします。以前からReverseProxyとして使っているApacheがデータの受け渡しのあたりでCPU100%使うbusy loopを起こすことがたびたびあり、これをいれてます。最新版のApacheでそもそも問題が解決しているかは検証していません。
FileETag None
多くの場合Cache-Contorl/Expiresを使うのでETagは必要ないと思います。デフォルトのFileETagは値の計算にinode番号を使うので複数のサーバから同じファイルを送信している場合、サーバ毎に異なるETagが生成されてしまいます。その際には、「Size」とだけ指定するのがお勧めです
NameVirtualHost *:80
<VirtualHost *:80>
ServerName dummy.example.com
...
</VirtualHost>
<VirtualHost *:80>
ServerName yourservice.com
...
</VirtualHost>
IPアドレスや意図しない逆引きアドレスからアクセスされないように、最初にダミーのVirtualHostを設定します。IPアドレスや逆引きアドレス、また意図しない他のアドレスでアクセスされた場合、最初のVirtualHostが選ばれます。エラーページを出してもいいですし、正しいURLへの誘導を行うのもいいでしょう。
合わせて参考にしたい
まぁ、このblogのサーバはほぼデフォルトで動いているんですけどね