カメノドットコム
Debian大好きでメインで節操ない感じ。
GMOもわりと好き。
RSS feedly

Apache2.4のevent_mpmをチューニング

Apache2.4 を event_mpm でインストールしましたので、チューニングを行います。
せっかく PHP7 も php-fpm で動いてますので、やっぱりチューニングします。
サーバスペックによって最適な値が変わりますので、自分の環境に合わせて設定しましょう。
Apache に付属している ab というコマンドでテストを行います。Apache Bench という広く使われているツールです。

ab コマンドはDOS攻撃にもなります。自分とこのテスト以外に使わないでください。

---- [PR] ----
現在契約中 : GMOクラウドのVPS : お名前.com
今後契約するかも : お名前.com VPS
--------------

Apache2.4で10万アクセス捌いてみる

いわゆる C10K問題 もありますし、せっかくの event_mpm なので「1万 のクライアントが、同時に 10 のアクセス」という世界にチャレンジしようと思います。
がんばれアパッチ。同時接続総数 10万 だぞ!

デフォルト設定で問題ないサーバは少ないです。
まずは「httpd.conf」で MPM の設定を変更できるようにして「httpd-mpm.conf」をいじっていきます。

# vi /opt/httpd_01/conf/httpd.conf
# event_mpm を変更できるようにする
Include conf/extra/httpd-mpm.conf
# vi /opt/httpd_01/conf/extra/httpd-mpm.conf
# event_mpm のデフォルト設定
<IfModule mpm_event_module>
    StartServers             3
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadsPerChild         25
    MaxRequestWorkers      400
    MaxConnectionsPerChild   0
</IfModule>
# svc -d /etc/service/htttpd-01    // Apacheを停止
# svc -u /etc/service/htttpd-01    // Apacheを起動
# /opt/httpd_01/bin/apachectl -V | grep MPM    // event_mpm になっているか確認
Server MPM:     event

確実に設定を反映できるように daemontools で停止してから改めて起動しています。
最後に event_mpm で動いてるかを確認しました。

テスト用ページは テスト用ファイル群ターボール にまとめてみました。自分で作るのが面倒な方は wget して解凍して使ってください。
ちなみに セメント樽の中の手紙 をお借りして HTML5 に変換、本文の第一段落を表示するものです。
データベースには同じデータを複数格納し、そこからデータを引き出す形にしてます。PHP7 もテストするので。
ディレクトリ構成とパーミッションなどは下記の通り。中身の変更はご自由にどうぞでございます。

htdocs/                          755
      +- test/                   707
             +- test.html        644     4.3  KB
             +- test.php         644    996    B
             +- default.css      644    195    B
             +- test.db          606     60   KB

とりあえず、デフォルト設定のままで HTML にアクセスしてみることにします。
カリカリチューニングはしないので VPS のローカルアクセステストにしました。
また、設定変更と ab のあとは daemontools で停止と起動を行い、初期化しています。

$ ab -c 10000 -n 100000 http://localhost/test/test.html
Benchmarking localhost (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
apr_socket_recv: Connection reset by peer (104)
Total of 99064 requests completed

惜しい! あとちょっとですよ。
調整してやれば 10万 アクセスを捌けそうです。いい感じですー。
ウチは 3コア なので、とりあえずコア数で揃えた設定をしてみました。王道の設定方法です。
ベンチのコマンドは ab -c 10000 -n 100000 http://localhost/test/test.html を延々と繰り返してます。

<IfModule mpm_event_module>
    StartServers           3
    MinSpareThreads        3
    MaxSpareThreads        3
    ThreadsPerChild        3
    MaxRequestWorkers      9
    MaxConnectionsPerChild 0
</IfModule>
// 諸々省略して最後の結果
apr_socket_recv: Connection reset by peer (104)
Total of 98873 requests completed

あれ? requests completed が減ってしまいました。
「StartServers」「MinSpareThreads」の2つは コア数 で固定して「MaxConnectionsPerChild」は 0 (無制限) で固定、あとの数字を色々いじってみます。
どうやら子プロセスが少なすぎるようなので、じわじわ増やしたり減らしたりしてみました。
そしてただひとつ「apr_socket_recv: Connection reset by peer (104)」を吐かない設定値がありました。

<IfModule mpm_event_module>
    StartServers             3
    MinSpareThreads          3
    MaxSpareThreads         15
    ThreadsPerChild         10
    MaxRequestWorkers      150
    MaxConnectionsPerChild   0
</IfModule>
Server Software:        Apache
Server Hostname:        localhost
Server Port:            80

Document Path:          /test/test.html
Document Length:        4362 bytes

Concurrency Level:      10000
Time taken for tests:   42.689 seconds
Complete requests:      100000
Failed requests:        400
   (Connect: 0, Receive: 0, Length: 400, Exceptions: 0)
Total transferred:      457770792 bytes
HTML transferred:       434463924 bytes
Requests per second:    2342.53 [#/sec] (mean)
Time per request:       4268.892 [ms] (mean)
Time per request:       0.427 [ms] (mean, across all concurrent requests)
Transfer rate:          10472.08 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0 1408 2127.8   1104   15257
Processing:    10  507 1830.3    242   35067
Waiting:        3  341 899.2    169   27764
Total:         22 1914 2759.0   1355   35067

Percentage of the requests served within a certain time (ms)
  50%   1355
  66%   1475
  75%   1704
  80%   3301
  90%   3511
  95%   7361
  98%   9346
  99%  15468
 100%  35067 (longest request)

……うん。無理(超笑顔)
GMOクラウドのVPS の 2GBプラン(3vCPU) では無理なようです。Unix Bench を見る限りでは、実質 2vCPU の性能しかないからなー。
まぁ、限界が見えたのでヨシとしましょう。
てことで、自分のサイトにふさわしいチューニングに変更します。プランBです。

自サイトに適正なApache2.4のチューニング

当然ですが 1万PV/日 とかありません。
ぶっちゃけ、小規模サイトです。明確に。はっきりと。
「10 のクライアントが、同時に 10 のアクセス」で充分なレベルです(笑)

とはいうものの、こうしてまともなコンテンツをやっと作成できるようになりましたし。
これからも頑張りますし。
「100 のクライアントが、同時に 10 のアクセス」
このくらいの見栄を張りたいナ、と思うわけです。
どっかで紹介されたとしても、ウチみたいな技術系もどきサイトにアクセスがいきなり集中するとも思えませんしね!
とりあえず、ギリギリで 10万 コンプリートした下記設定のベンチを基準にして調整していきます。

<IfModule mpm_event_module>
    StartServers             3
    MinSpareThreads          3
    MaxSpareThreads         15
    ThreadsPerChild         10
    MaxRequestWorkers      150
    MaxConnectionsPerChild   0
</IfModule>

現実的(笑)なベンチを取るということで、ADSL で 5〜10Mbps 程度の自宅からのテストに変更します。
ab -c 100 -n 1000 http://example.com/test/test.html でテストします。
設定変更したりアタックかけたりしたあとは daemontools で停止・起動するのは 10万 にチャレンジした時と同じです。

……自宅からテストしてみましたら。
通信速度にバラつきがありすぎて比較できませんでしたYO!
VPS でのローカルテストに変更します……
ab -c 100 -n 1000 http://localhost/test/test.html にコマンドも変更です。

チューニングのポイントになるは以下の 4項目 でしょう。
Complete requests
Failed request
Requests per second: [#/sec] (mean)
Time per request: [ms] (mean, across all concurrent requests)

詳細を全部貼り付けてたら大惨事なページになるので 片っ端から試した Apache Bench リスト にリンク貼っときます。調整の際の参考にしてくださると嬉しいです。
設定値と目安になる項目の結果を表にしてみました。

StartServers 3
MinSpareThreads 3
MaxSpareThreads 15
ThreadsPerChild 10
MaxRequestWorkers 150
MaxConnectionsPerChild 0
StartServers 3
MinSpareThreads 3
MaxSpareThreads 12
ThreadsPerChild 10
MaxRequestWorkers 120
MaxConnectionsPerChild 0
StartServers 3
MinSpareThreads 3
MaxSpareThreads 4
ThreadsPerChild 4
MaxRequestWorkers 16
MaxConnectionsPerChild 0
StartServers 3
MinSpareThreads 3
MaxSpareThreads 3
ThreadsPerChild 3
MaxRequestWorkers 3
MaxConnectionsPerChild 0
StartServers 3
MinSpareThreads 3
MaxSpareThreads 3
ThreadsPerChild 1
MaxRequestWorkers 1
MaxConnectionsPerChild 0
Complete requests 1,000 1,000 1,000 1,000 1,000
Failed request 0 0 0 0 0
Requests per second 6625.72 6807.49 6761.05 7017.94 6594.96
Time per request 0.151 0.147 0.148 0.142 0.152

えーと。
身も蓋もない結果になりました。

とりあえず コア数 に揃えておけ。

時間を返して。
面白かったからいいけど。
頭ひとつ飛び抜けた設定で、どこまでのアクセスに耐えられるのかもテストしてみました。
「100 のクライアントが、同時に 10 のアクセス」から始めて、クライアント数を 100 ずつ増やしての耐久テストです。

結果は「800 のクライアントが、同時に 10 のアクセス」で初めてエラーが出ました。しかし「Length」だけです。続行フラグ。
さらに増やし続けたところ、エラーが出ないこともありつつどんどん増やせます。同時接続総数 1万 を突破してもエラー無しだったりもします。どこまで行く気だい、アパッチさん。
「3,300 のクライアントが、同時に 10 のアクセス」で、ついに「apr_socket_recv: Connection reset by peer (104)」となりました。処理リクエスト数は 32,735 件です。
この時の使用メモリは 1.8GB 程度でした。VPS のスペック上、物理限界ですね。
……あれ? なんかすごくねーですか。この event_mpm って。
ウチのアクセス状況だと、余裕で捌けます。2台ぶら下げても大丈夫そうです。
イヤッフー!

チューニングしてて気づいたこと。
ログファイルが大きくなると、エラーが出やすくなってパフォーマンスが落ちます。
毎日ログを回すのがいいようです。再起動もかけますので、パフォーマンス向上につながるでしょう。
大決定した設定を載せておきます。環境によって大きく異なると思いますので参考程度に。

<IfModule mpm_event_module>
    StartServers             3
    MinSpareThreads          3
    MaxSpareThreads          3
    ThreadsPerChild          3
    MaxRequestWorkers        3
    MaxConnectionsPerChild   0
</IfModule>

すっごく長くなりましたので php-fpm のチューニングは次のページで。

Sponsored Link