中規模サイトのApacheチューニング

__イマドキApacheのチューニングなんてしなくてもちゃんと動くだろうと思ってたら痛い目にあったので、書いてます。基本をおろそかにするとよくないですね。__


![21731ad65f5a1c5459f56a17e58eb544_s.jpg](https://qiita-image-store.s3.amazonaws.com/0/32789/3f331bc9-a7f2-386b-fd38-4aa727b4fca6.jpeg)

[追記]
スライドも作ってみました。良かったら見てください。
http://www.slideshare.net/yumemikouda/apache-69549461


## 前提
- Apache2.x系です
- preforkでの起動です
- 写真はイメージです
- WEBサーバ数台＋DB2台（マスター1、レプリカ1）程度のトラフィックを前提
    - 大規模だとまた話が変わってきます


## mpm関連
### パラメータ説明

| 項番 | 項目 | 説明 | 補足 |
|:-:|:-:|:--|:--|
| 1 | StartServers | Apache起動時の子プロセス数 | Apache起動時にまずはここで設定された数の子プロセスを起動します |
| 2 | MinSpareServers | 待機時の最小子プロセス数 | 子プロセスがMinSpareServersより少なくなったら、この値まで子プロセスを上げます |
| 3 | MaxSpareServers | 待機時の最大子プロセス数 | 子プロセスがMaxSpareServersより大きくなったら、この値まで子プロセスを下げます |
| 4 | ServerLimit | 設定可能なサーバプロセス数の上限 | MaxClientsを256以上に設定したい場合はServerLimitも設定する必要があります。また、 **MaxClientsの上に書かないと効きません** |
| 5 | MaxClients | 最大の小プロセス数 | この数≒最大の同時接続数です |
| 6 | MaxRequestsPerChild | 1子プロセスが処理するリクエスト数 | ここで設定された数のリクエストを処理すると子プロセスが死んで、新しい子プロセスに生まれ変わります。"0"にすると無制限にリクエストを処理します |

### チューニング
- 忙しいサイトなら1-5は全て同じ値に設定してしまいましょう
- どうせ忙しいサイトならMaxClientには達するんだと思います。であれば、変にメモリをケチらずに最初からMaxClientまで子プロセスを起動してしまったほうがレスポンスが良いです
- 急激なトラフィック増の際に多くの子プロセスが一気に起動することでシステムのロードがスパイクし、レスポンスを返せなくなることがあるからです
- mod_wsgiとかmod_perlとか読み込んでいる場合は特に子プロセス起動時のオーバーヘッドは馬鹿にできません
- かといって、MaxRequestsPerChildを"0"にして子プロセスを殺さないようにするのはやめたほうが良いです。子プロセスのメモリ使用量が肥大化し、システムでスワップが発生する可能性があります。

### MaxClient数の算出方法
- サーバの物理メモリを消費し尽くしてスワップさせないことが重要です
- httpd1プロセスあたりのメモリ使用量はtopコマンドでおおまかに把握することができます
    - topコマンドで表示されるRES（物理メモリ使用量）です
    - 各プロセス毎に処理している内容によりメモリ量の増減がありますので、いくつかのhttpdプロセスをサンプリングしておおまかに平均値を算出しましょう
- **サーバの物理メモリ量 ＞ 上記で算出した1httpdプロセスあたりのメモリ使用量の平均値×MaxClient数＋他のプロセスが使うであろうメモリ使用量** となるようにMaxClient数を設定しましょう

```
top - 17:29:42 up 6 days, 17 min,  4 users,  load average: 0.92, 1.10, 1.23
Tasks: 237 total,   2 running, 235 sleeping,   0 stopped,   0 zombie
Cpu(s): 24.0%us,  0.8%sy,  0.0%ni, 74.7%id,  0.0%wa,  0.0%hi,  0.5%si,  0.1%st
Mem:  15343788k total, 10152612k used,  5191176k free,   231068k buffers
Swap:        0k total,        0k used,        0k free,  2336312k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
26835 apache    20   0  328m  59m 6400 R 29.6  0.4   0:48.24 httpd
26870 apache    20   0  331m  62m 5884 S 27.2  0.4   0:42.28 httpd
26607 apache    20   0  317m  49m 5872 S 20.3  0.3   0:25.53 httpd
27481 apache    20   0  316m  48m 5876 S 12.3  0.3   0:36.53 httpd
26730 apache    20   0  317m  48m 5880 S  9.6  0.3   0:34.03 httpd
26583 apache    20   0  320m  51m 5884 S  1.3  0.3   0:32.28 httpd
```

## HTTPタイムアウト
### パラメータ説明

| 項番 | 項目 | 説明 | 補足 |
|:-:|:-:|:--|:--|
| 1 | Timeout | リクエストを受け取ってから処理完了までの待機時間| 下記のそれぞれの時間にTimeoutが設定されます。1. GET リクエストを受け取るのにかかる総時間 2. POST や PUTリクエストにおいて、次の TCP パケットが届くまでの待ち時間 3. レスポンスを返す際、TCP の ACK が帰ってくるまでの時間  |
| 2 | KeepAlive | 持続的接続を許可する |HTTPで定義されているKeepAlive接続を有効にする設定。1つのTCP接続で複数のHTTPリクエストが処理されるようになる |
| 3 | MaxKeepAliveRequests |持続的接続で許されるリクエスト数 |1回のKeepAlive接続で処理可能なリクエスト数 |
| 4 | KeepAliveTimeout |持続的な接続で次のリクエストを待つ時間 |KeepAliveをOnにしていた場合のみ有効 |


### チューニング
- Timeoutのデフォルト値は300秒ですが、長過ぎますので、短くしましょう。応答のないクライアントを5分も待つやさしさは不要です。我々は忙しいんです
- KeepAliveは幻想の機能です。忙しいサイトなら使うのやめましょう。忙しくないサイトならどちらでも良いと思います
- KeepAliveを有効にすれば、たしかに1回の接続でクライアントから複数のリクエストを送ることができるため、TCP接続のオーバーヘッドやコネクション数が抑えられる気がします
- しかし、それは幻想です。結局、1クライアントから複数のTCPコネクションを張られ、そのコネクションが長時間専有されることで、Apacheの子プロセスをあっという間に消費しつくされてしまいます
- KeepAliveをOffにしていればMaxKeepAliveRequestsやKeepAliveTimeoutはいくつでもかまわないです
- 上記のようにKeepAliveは切ったほうが良いですが、AWSのELB配下では切らない方が良いようです → [Amazon ELBをうまくつかうには、KeepAliveを有効にしよう。Timeoutは60秒よりだいぶ長くしよう。その背景。](http://debiancdn.wordpress.com/2012/06/14/amazon-elb%E3%82%92%E3%81%86%E3%81%BE%E3%81%8F%E3%81%A4%E3%81%8B%E3%81%86%E3%81%AB%E3%81%AF%E3%80%81keepalive%E3%82%92%E6%9C%89%E5%8A%B9%E3%81%AB%E3%81%97%E3%82%88%E3%81%86%E3%80%82timeout%E3%81%AF60/)


## HTTP通信圧縮
### パラメータ説明

| 項番 | 項目 | 説明 | 補足 |
|:-:|:-:|:--|:--|
| 1 | SetOutputFilter | 圧縮機能を有効にします。| mod_deflateモジュールを使い圧縮します。フィルタとして`DEFLATE`を指定しると圧縮機能が有効になります。 |
| 2 | AddOutputFilterByType | 圧縮対象とするMIMEタイプを指定します。| htmlやcssはもちろんjavascriptなども圧縮しましょう|

### チューニング
- PNGやJPEGなどの画像ファイルはすでに圧縮されているため圧縮対象から外すと無駄な圧縮処理をしないですみます
- 古いブラウザではバグなどにより圧縮対応していないものもあるので無効にします（今どき使ってる人いないと思いますが。。。）
- 実際のconfの書き方は下記サイトを参考にしてみてください
    - [Apacheのmod_deflateでコンテンツを圧縮してサイトを高速化する方法](http://oxynotes.com/?p=6519)


## ログファイル関連
### HostnameLookups
- アクセスをログファイルに記録する際に接続元IPアドレスをDNSで逆引きするオプションです
- DNSの逆引きは時間がかかることが多いですので、Offにするのは必須です


# 仲間募集
[株式会社スピカ](http://spika.co.jp)では一緒に切磋琢磨できるエンジニアの方を募集しています！ぜひ、[こちら](https://www.wantedly.com/companies/spika/projects)をご覧ください！！