PHPとWebサーバの組み合わせについて

2015-12-17
PHP
Benchmark

注意
下記には、結構な量の嘘が混入されています。
詳細は、PHP BLT #2に行ってきたを参照下さい。

ちょっと遅くなりましたが、この記事はPHPアドベントカレンダー2015の17日目の記事です。

タイトルの件ですが、2015年12月現在で、PHPとWebサーバの組み合わせって、一体どんな構成にすると良いかな?と
ふと疑問に思ったので、自分の環境で、ベンチマークを取って見ることにしました。

ベンチマーク対象のPHP&Webサーバの組み合わせ

以下の4つの組み合わせでベンチを取って見ました。

1. NginxとPHP-FPM

近年、PHPでハイパフォーマンスを出すという場合によく取られる構成かと思います。
ISUCONに参加しているPHP系チームもこの構成を取るチームが多かったですね。

2. Apache2.4(prefork)とmod_php

これぞPHP!!という王道の構成です。
何も考えずにDocumentRootにphpファイルを放り込めば動きます。

3. Apache2.4(prefork)とmod_php with 静的ファイル用Nginx

ひとつ前の構成とほぼ同じですが、静的ファイルの処理用に前段にNginxを配置しています。

今回のベンチマークでは、Apacheを8080ポートで動かして、phpへのリクエストのみapache側にまわすようにしました。
理屈としては、mod_phpをロードしたApacheのプロセスが、静的ファイルの処理で使われないので、プロセスの無駄遣いが無くなります。

4. Apache2.4(event)とPHP-FPM

実は、今回はコレを試したくて、ベンチマークしたようなものでした。
Nginxに比べてどれくらいパフォーマンスが出るのか楽しみです。

ベンチマークを行った環境

実行したマシン

  • マシン : MacBook Pro (メモリ16GB)
  • 仮想サーバ : VirtualBox(Vagrant利用)
  • CPU割当 : 1
  • メモリ割り当て : 500MB

はい、すいません。普段、自分で持ち歩いているMacを使いました。

OS、その他ミドルウェア、PHPのバージョン

  • Ubuntu14.04.3 LTS
  • Apache2.4.17
  • PHP 7.0.0
  • Nginx 1.4.6

環境構築は、Vagrant+Ansibleを使っています。 今回のベンチマーク環境は、vagrant upで一発で構築出来ます。
Vagrantfileはこちら => https://github.com/hanhan1978/bench_vagrants

vboxsfが遅いので、nfsで共有フォルダをshareするように設定しています。
Apache, Nginx, PHPの設定はデフォルトのままです。特にいじらない状態で比較しています。

ベンチマークに利用したアプリケーション

簡単なToDoリストを表示するアプリをLaravelで作成しました。
Laravelの設定その他は、極力いじっていません。

/todoというURLにアクセスすると画像ファイルが12個と、jquery, cssを読み込んだ上で、DBに格納されたToDoリスト(全6件)を表示します。
リポジトリはこちら => https://github.com/hanhan1978/benchapp

ベンチマーカー

siegeを使いました。

siege -b -t60s -f urls.txt

urls.txtには、Todoリストを表示するURLと、ページ内の画像ファイル、CSS、JSのURLが列挙してあります。
一般的なウェブアプリと同じようなリクエストをWebサーバに対して行うようにしました。

リクエストは、各環境に対して3回ずつ行った上で、平均値を計算しました。(小数点二位以下は四捨五入)

※上記のVagranfileと同じリポジトリに、siegeの実行オプションを記述したテスト実行用のシェルが入ってます。

結果

個別の数値というよりは、他の環境との比較で見てもらうと良いかなと思います。

NginxとPHP-FPM Apache2.4(prefork)とmod_php Apache2.4(prefork)とmod_phpとNginx Apache2.4(event)とPHP-FPM
Transaction 14427.33 11437.5 15220.25 10301.33
Availavility(%) 100 100 100 100
Elapsed time(sec) 59.84 59.5 59.14 59.39
Data Transferred(MB) 868.29 648.97 916.46 583.83
Response Time(sec) 0.067 0.08 0.063 0.09
Transaction rate(trans/sec) 241.14 192.3 257.42 173.46
Throughput(MB/sec) 14.51 10.91 15.50 9.83
Concurrency 14.96 14.82 14.95 14.94
Successful Transactions 14427.33 11437.5 15220.25 10301.33
Failed Transactions 0 0 0 0
Longest Transaction 2.54 7.73 3.17 2.51
Shortest transaction 0 0 0 0

NginxとPHP-FPMの組合わせ、またはApache(prefork)とmod_php&前段Nginxの組み合わせが、好成績でした。

期待していたApache2.4のmpm_eventさんは、性能ふるわず!残念!
静的ファイルを混ぜたリクエストだったので、Apache(prefork)とmod_phpの組み合わせは、予想通り少し劣るという結果となりました。 ベンチマークを取り終わった後に、mpm_eventの設定を調整してみたのですが、結果はあまり変わらずだったので

mpmevent使いまくっている人は、なんか教えて下さい m( _)m

まとめ

結果としては、皆がなんとなく良いと思っているNginxとPHP-FPMの組み合わせは、静的ファイルも混ざった現実世界のウェブサービスのリクエストに対して、まあまあ良い性能を発揮するということが再確認できました。

意外とまではいかないのですが、mod_phpの前段にNginxで静的ファイルを捌くようにした構成も成績がよくて驚きました。preforkとmod_phpの組み合わせがPHPの処理ということに特化すれば、ちゃんとパフォーマンス出せるということを再認識できますね。
というわけで、今まで通り、何も考えずにNginxとPHP-FPM使うもよし、mod_php使うもよし。

ただし、静的ファイルがいっぱいあるときは、ちゃんと考えろよということで、オシマイでございます。

余談

静的ファイルのリクエストを止めて、PHPファイルだけのアクセスでベンチマークを取ると、どの環境でも大体同じくらいのレスポンスが出ました。

なので、このblogを読んで、「NginxとPHP-FPMにするんだ!」ではなくて、自分のサービスにくるリクエストの中身をきちんと計測した上でベターな選択肢を選んでいただければと思います。
ベンチマークやったの初めてなので、「ここはこうしたほうがいいよ」とか「これじゃ駄目じゃん」とかあったら、ジャカジャカご指摘下さいませ
m( )m