LIFULL Creators Blog

LIFULL Creators Blogとは、株式会社LIFULLの社員が記事を共有するブログです。自分の役立つ経験や知識を広めることで世界をもっとFULLにしていきます。

PHPコンパイルによる高性能のFastCGIウェブサーバー構築とチューニングに関するお話し(3)

こんにちは。新規事業本部・金融グループの金(成奉)です。

前回( PHPコンパイルによる高性能のFastCGIウェブサーバー構築とチューニングに関するお話し(2) - 株式会社ネクスト エンジニアBlog )に引き続き、FastCGI基盤ウェブサーバーのPHPコンパイル構築、チューニング、設定などについてお話したいと思います。

PHPビルド後の簡単な作動確認について

テストは「make test」できますが、時間がかかるため、コンパイル・ビルドができているかを確認するため、以下のコマンドを実行して、エラーにならなければ、ビルド構築は成功です。

モジュール確認
php -i | less
CGI作動確認

HTMLで出力されます。

php-cgi -i >php_info.htm
コマンドラインでの作動確認

エラーなしで、実行できれば、正常にモジュールがロードされて、インストールは完了です。エラーの場合は、ソース修正またはオプションを変更して再コンパイルする必要がある。

php -r 'echo "テスト\n";'
php -r 'echo time()."\n";'
php -r 'echo md5('test')."\n";'
PHP-FastCGIプロセスサーバ(php-fpm)確認

単体では確認できないため、Apacheの設定またはNginxをインストールしてから確認します。

ApacheとPHPモジュール設定(PHP検証のため臨時設定)

Apacheとの比較のための臨時設定

サーバネーム追加
echo "ServerName localhost" >> /etc/httpd/conf.d/servername.conf
PHPインストール時にApache設定に自動的に追加されるPHPモジュールのコメントにします
sed -i 's/LoadModule php5_module/\#LoadModule php5_module/g;' /etc/httpd/conf/httpd.conf
PHPモジュールの設定(拡張子:php)
cat > "/etc/httpd/conf.d/php.conf" << EOF
LoadModule php5_module modules/libphp5.so
AddType application/x-httpd-php .php
EOF

PHPのApacheでの動作確認

cat > "/var/www/html/info_test.php" <<EOF
<?php
echo phpinfo();
?>
EOF
Apache Service Start
service httpd start
w3mでの確認
yum install -y w3m
w3m http://www.example.com/info_test.php
w3m終了
Q

Apache Bench(apache2+mod_php)

PHPモジュールはPreforkモデルでしか動作しません。phpinfo()のベンチマークです。

測定
ab -n 10000 -c 200 http://www.example.com/info_test.php
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.example.com (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        Apache
Server Hostname:        www.example.com
Server Port:            80

Document Path:          /info_test.php
Document Length:        95999 bytes

Concurrency Level:      200
Time taken for tests:   19.618 seconds
Complete requests:      10000
Failed requests:        9980
   (Connect: 0, Receive: 0, Length: 9980, Exceptions: 0)
Write errors:           0
Total transferred:      964672277 bytes
HTML transferred:       963357692 bytes
Requests per second:    509.72 [#/sec] (mean)
Time per request:       392.369 [ms] (mean)
Time per request:       1.962 [ms] (mean, across all concurrent requests)
Transfer rate:          48019.25 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   37  37.3     26     146
Processing:    13  354  58.5    357     625
Waiting:        3  203 143.0    142     553
Total:         26  391  51.3    388     629

Percentage of the requests served within a certain time (ms)
  50%    388
  66%    397
  75%    406
  80%    414
  90%    448
  95%    477
  98%    501
  99%    514
 100%    629 (longest request)
Apache Service Stop
service httpd stop

mod_fastcgiインストール

ソースダウンロード
cd /opt/src
wget http://www.fastcgi.com/dist/mod_fastcgi-current.tar.gz
解凍とコンパイル
tar zxvf mod_fastcgi-current.tar.gz
cd mod_fastcgi-2.4.6/
cp Makefile.AP2 Makefile
make top_dir=/usr/lib64/httpd
make install top_dir=/usr/lib64/httpd
インストールバイナリ確認
ldd /usr/lib64/httpd/modules/mod_fastcgi.so
        linux-vdso.so.1 =>  (0x00007ffffeeea000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f478e38c000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f478dff8000)
        /lib64/ld-linux-x86-64.so.2 (0x0000003b69000000)

Apache2/FastCGI設定(PHP-FPM)

性能比較のために拡張子を臨時的に「.fphp」に設定しています。本番運用時には「.php」に戻します。Location設定は、URLへのダイレクトアクセスを防ぐ内容です。Action内部でリダイレクトした後、fcgi-binのURLが使えるようにするために「env=REDIRECT_STATUS」を設定します。

cat > "/etc/httpd/conf.d/php-fpm.conf" <<'EOF'
LoadModule fastcgi_module modules/mod_fastcgi.so
<FilesMatch "\.(fphp|html)$">
    SetHandler application/x-httpd-php
</FilesMatch>
Action application/x-httpd-php /fcgi-bin/php-fpm virtual
Alias /fcgi-bin/php-fpm /fcgi-bin-php-fpm
<Location /fcgi-bin/php-fpm>
    Order Deny,Allow
    Deny from All
    Allow from env=REDIRECT_STATUS
</Location>
FastCgiExternalServer /fcgi-bin-php-fpm -appConnTimeout 10 -idle-timeout 250 -socket /var/run/php-fpm.sock -pass-header Authorization
EOF

★重要★上記設定で「-appConnTimeout 10 -idle-timeout 250」は必ず設定するようにします。idele-timeoutはデフォルトで30秒になっていますが、場合によっては十分ではないため長く設定しておきます。「FastCGI: incomplete headers (0 bytes) received....」というエラーが吐出され、応答しなくなるケースがまれにあります。このエラーが発生した際は、「-idle-timeout」の時間をもっと長く設定することで解消できます。詳細の内容は以下のサイトを参照してください。

FastCGI設定マニュアル: http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html

PHP-FPMサービス確認と登録

サービス動作テスト
service php-fpm start
service php-fpm stop
サービスに追加テスト
chkconfig php-fpm on
サービスから削除テスト
chkconfig php-fpm off
サービス確認
chkconfig --list php-fpm
php-fpm         0:off   1:off   2:off   3:off   4:off   5:off   6:off
サービス登録
chkconfig php-fpm on

PHP-FPM設定

グローバルとプール設定に分けます。多くの設定オプションがありますが、下記のように短く設定しても問題はありません。FastCGIのプロセスについては、固定(static)での設定を推奨します。
Apache-1.3の初期バージョンから、FastCGIを使ってみましたが、ダイナミック(dynamic)での設定では、様々なトラブルに遭遇した経験があります。FastCGIプロセスは、待ち受けるプロセスであるため、メモリリークを注意しなければなりません。PHP-FPMでリクエストの最大数(pm.max_requests )を設定していれば、自動で子プロセスをリスタートしてくれる機能があり、メモリリークを防ぎます。メモリの状況を確認しながら、固定(static)で立ち上げる子プロセス数を決定します。
設定時に注意しなければならないのは、デフォルトで生成されたソケットファイルにはapacheまたはnginx権限ではアクセスできないため、listen.modeで権限を0666にする必要があります。2Gメモリのマシーンでプロセス数を100にしても問題なく動作確認できました。サイトによって異なりますのでHTOPをインストールしてメモリの使用率を見ながら調整します。ププロセス数固定(static)の設定では一度ロードされると固定でメモリを確保します。ダイナミック(dynamic)の設定では、メモリの使用率が設定範囲内でアクセス数によって変動します。

php-fpm.conf設定
mkdir /etc/fpm.d
rm -f /etc/php-fpm.conf
グローバル設定
cat > "/etc/php-fpm.conf" <<EOF
[global]
pid = run/php-fpm.pid
error_log = log/php-fpm.log
log_level = notice
daemonize = yes
include=/etc/fpm.d/*.conf
EOF
プールの設定(Apache検証用権限)

Apacheの場合は下の設定に切り替えて検証します。

cat > "/etc/fpm.d/www.conf" <<'EOF'
[apache]
user = apache
group = apache
listen = /var/run/php-fpm.sock
listen.mode = 0666
pm = static
pm.max_children = 100
pm.max_requests = 1000
security.limit_extensions = .php .fphp .html .htm
EOF
プールの設定(Nginx検証用権限)

Nginxの場合は下の設定に切り替えて検証します。

cat > "/etc/fpm.d/www.conf" <<'EOF'
[nginx]
user = nginx
group = nginx
listen = /var/run/php-fpm.sock
listen.mode = 0666
pm = static
pm.max_children = 100
pm.max_requests = 1000
security.limit_extensions = .php .fphp .html .htm
EOF
php動作テストファイル作成
cat > "/var/www/html/info_test.php" <<EOF
<?php
echo phpinfo();
?>
EOF

Apache Bench(apache prefork + php-fpm)

PHP-FPMは、ソケット、スタティックプロセス設定で、ApacheのMPMは、preforkでベンチマークを行いました。手順は、上記の設定を反映してから、PHPモジュールをApacheから外してから保存、Apacheサービスを再起動します。

Apache(prefork)+php-fpm(socket,static)

PHPモジュール外し
sed -i 's/LoadModule/\#LoadModule/g;' /etc/httpd/conf.d/php.conf
sed -i 's/AddType/\#AddType/g;' /etc/httpd/conf.d/php.conf
サービス再起動
servie httpd restart
測定
ab -n 10000 -c 200 http://www.mhoken.com/info_test.fphp
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.mhoken.com (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        Apache
Server Hostname:        www.mhoken.com
Server Port:            80

Document Path:          /info_test.fphp
Document Length:        93626 bytes

Concurrency Level:      200
Time taken for tests:   17.830 seconds
Complete requests:      10000
Failed requests:        9052
   (Connect: 0, Receive: 0, Length: 9052, Exceptions: 0)
Write errors:           0
Total transferred:      939760915 bytes
HTML transferred:       938447640 bytes
Requests per second:    560.84 [#/sec] (mean)
Time per request:       356.605 [ms] (mean)
Time per request:       1.783 [ms] (mean, across all concurrent requests)
Transfer rate:          51470.65 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        2   59  33.6     54     281
Processing:    57  297  37.8    300     379
Waiting:        2   61  30.7     58     281
Total:        108  356  35.8    351     644

Percentage of the requests served within a certain time (ms)
  50%    351
  66%    360
  75%    366
  80%    372
  90%    387
  95%    398
  98%    413
  99%    506
 100%    644 (longest request)

Apache Bench(apache worker + php-fpm)

MPMをWorkerに切り替えてから、Apacheサービスを再起動します。ApacheにはPHPモジュールがロードされないように注意します。デフォルト設定では四つのWorkerが起動します。

Apache(worker)+php-fpm(socket,static)

ApacheのPHPモジュール外し
sed -i 's/LoadModule/\#LoadModule/g;' /etc/httpd/conf.d/php.conf
sed -i 's/AddType/\#AddType/g;' /etc/httpd/conf.d/php.conf
Apacheのworkerへの切り替え設定
sed -i 's/\#HTTPD=/HTTPD=/g;' /etc/sysconfig/httpd
サービス再起動
servie httpd restart
測定
ab -n 10000 -c 200 http://www.example.com/info_test.fphp
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.example.com (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        Apache
Server Hostname:        www.example.com
Server Port:            80

Document Path:          /info_test.fphp
Document Length:        93622 bytes

Concurrency Level:      200
Time taken for tests:   16.813 seconds
Complete requests:      10000
Failed requests:        10012
   (Connect: 0, Receive: 0, Length: 10012, Exceptions: 0)
Write errors:           0
Total transferred:      941082361 bytes
HTML transferred:       939767383 bytes
Requests per second:    594.79 [#/sec] (mean)
Time per request:       336.255 [ms] (mean)
Time per request:       1.681 [ms] (mean, across all concurrent requests)
Transfer rate:          54662.48 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1   64  33.0     62     188
Processing:    77  271  37.7    272     448
Waiting:        1   80  51.7     69     329
Total:        146  335  31.3    329     566

Percentage of the requests served within a certain time (ms)
  50%    329
  66%    335
  75%    339
  80%    345
  90%    373
  95%    394
  98%    417
  99%    435
 100%    566 (longest request)

Apacheの検証結果

ベンチマーク結果の「Failed requests」は、無視します。理由は、HTTPからアクセスして「phpinfo();」を出力すると毎回サイズが異なります。このサイズが異なる時には「Failed requests」になるようです。PHPの運用は、上記の検証のようにApacheでの基本構成は、「Apache(worker) + PHP-FPM(FastCGI)」が一番良いパフォーマンスが出ています。

Nginxコンパイル構築

nginxの依存性にあるライブラリーのインストール
yum -y install GeoIP-devel.x86_64
yum -y install bxslt-devel.x86_64
yum -y install perl-ExtUtils-Embed.x86_64
yum -y install pcre-devel.x86_64
RPM-GPG-KEYのインポート
rpm --import http://mirror.centos.org/centos/6.5/os/x86_64/RPM-GPG-KEY-CentOS-6
Nginxの最新安定版のインストール
rpm -i http://nginx.org/packages/centos/6/x86_64/RPMS/nginx-1.6.0-1.el6.ngx.x86_64.rpm
RPMのインストールディレクトリ確認
rpm -ql nginx
/etc/logrotate.d/nginx
/etc/nginx
/etc/nginx/conf.d
/etc/nginx/conf.d/default.conf
/etc/nginx/conf.d/example_ssl.conf
/etc/nginx/fastcgi_params
/etc/nginx/koi-utf
/etc/nginx/koi-win
/etc/nginx/mime.types
/etc/nginx/nginx.conf
/etc/nginx/scgi_params
/etc/nginx/uwsgi_params
/etc/nginx/win-utf
/etc/rc.d/init.d/nginx
/etc/sysconfig/nginx
/usr/sbin/nginx
/usr/share/nginx
/usr/share/nginx/html
/usr/share/nginx/html/50x.html
/usr/share/nginx/html/index.html
/var/cache/nginx
/var/log/nginx

RPMでインストールした理由は、各種設定ファイルを自動で配置させるためです。後は、ソースからダウンロードしてGoogle開発のオープンソース「ngx_pagespeed」をサポートできるようにコンパイルしてから実行バイナリ「/usr/sbin/nginx」を差し替えます。

Nginx及びソースダウンロード
cd /opt/src
wget -q http://nginx.org/download/nginx-1.6.0.tar.gz
tar zxvf nginx-1.6.0.tar.gz

wget -q https://github.com/pagespeed/ngx_pagespeed/archive/v1.8.31.4-beta.zip -O ngx_pagespeed-1.8.31.4-beta.zip
unzip ngx_pagespeed-1.8.31.4-beta.zip

cd ngx_pagespeed-1.8.31.4-beta/
wget -q https://dl.google.com/dl/page-speed/psol/1.8.31.4.tar.gz
tar -xzvf 1.8.31.4.tar.gz
コンパイル設定

コンパイルオプションの確認は既存RPMでインストールされているものと同じ構成にするため「nginx -V」コマンドで確認してpgespeedモジュールを最後に追加すします。

cd /opt/src/nginx-1.6.0
./configure --prefix=/etc/nginx \
    --sbin-path=/usr/sbin/nginx \
    --conf-path=/etc/nginx/nginx.conf \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --pid-path=/var/run/nginx.pid \
    --lock-path=/var/run/nginx.lock \
    --http-client-body-temp-path=/var/cache/nginx/client_temp \
    --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
    --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
    --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
    --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
    --user=nginx --group=nginx \
    --with-http_ssl_module \
    --with-http_realip_module \
    --with-http_addition_module \
    --with-http_sub_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_mp4_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_random_index_module \
    --with-http_secure_link_module \
    --with-http_stub_status_module \
    --with-http_auth_request_module \
    --with-http_xslt_module \
    --with-http_image_filter_module \
    --with-http_degradation_module \
    --with-mail \
    --with-mail_ssl_module \
    --with-file-aio \
    --with-ipv6 \
    --with-http_spdy_module \
    --with-cc-opt='-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' \
    --with-ld-opt=' -Wl,-E' \
    --add-module=/opt/src/ngx_pagespeed-1.8.31.4-beta
コンパイル
make -j10
既存バイナリ上書き
\cp objs/nginx /usr/sbin/nginx

Nginx設定(検証のため臨時簡単設定)

Nginx基本設定

worker_processesはCPUのコア数を設定します。

既存設定バックアップ
\cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf_backup
設定ファイル上書き
cat > "/etc/nginx/nginx.conf"<< 'EOF'
user  nginx;
worker_processes  3;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush      on;

    keepalive_requests 100;
    keepalive_timeout 10;

    gzip  on;
    gzip_static on;
    gzip_comp_level 2;
    gzip_buffers 64 8k;
    gzip_min_length 1100;
    gzip_types        text/plain 
                      text/xml 
                      text/css 
                      application/xml 
                      application/xhtml+xml 
                      application/rss+xml 
                      application/atom_xml 
                      application/javascript 
                      application/x-javascript 
                      application/x-httpd-php;
    gzip_disable      "MSIE [1-6]\.";
    gzip_disable      "Mozilla/4";
    gzip_vary  on;
    gzip_proxied      any;
    gzip_http_version 1.1;

    server_tokens off;

    include /etc/nginx/conf.d/*.conf;

}
EOF
Nginxサーバ設定

既存Apacheベンチマークディレクトリをそのまま設定してベンチマークを行います。

\cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf_backup

cat > "/etc/nginx/conf.d/default.conf" <<'EOF'
server {
    listen       80;
    server_name  localhost;

    location / {
        root   /var/www/html/;
        index  index.php;
        try_files $uri $uri/ /index.php?$uri&$args;
    }

    location ~ \.php$ {
        root           /var/www/html/;
        fastcgi_pass   unix:/var/run/php-fpm.sock;
        fastcgi_index  index.php;
        include        fastcgi_params;
        fastcgi_param  REMOTE_ADDR $remote_addr;
        fastcgi_param  REMOTE_PORT $remote_port;
        fastcgi_param  SERVER_ADDR $server_addr;
        fastcgi_param  SERVER_PORT $server_port;
        fastcgi_param  SERVER_NAME $server_name;
        fastcgi_param  CONTENT_TYPE $content_type;
        fastcgi_param  CONTENT_LENGTH $content_length;
        fastcgi_param  QUERY_STRING $query_string;
        fastcgi_param  PATH_INFO  $fastcgi_path_info;
        fastcgi_param  REQUEST_METHOD $request_method;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param  SCRIPT_NAME $fastcgi_script_name;
        fastcgi_param  REQUEST_URI $request_uri;
        fastcgi_param  DOCUMENT_URI $document_uri;
        fastcgi_param  DOCUMENT_ROOT $document_root;
        fastcgi_param  SERVER_PROTOCOL $server_protocol;
        fastcgi_param  GATEWAY_INTERFACE CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE nginx/$nginx_version;
        fastcgi_param  HTTPS $https;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 16k; #4096k total
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
        fastcgi_max_temp_file_size 0; #disable buffering to disk
        client_max_body_size 0; #Allow large uploads
    }
}
EOF

Apache Bench(nginx + php-fpm)

Apacheとほぼ同じ設定になります。「gzip on」の方が「gzip off」より少し遅くなりますが、ほぼ変わらなかったため、「gzip on」の状態で測定しました。

ab -n 10000 -c 200 http://www.example.com/info_test.php
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.mhoken.com (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        nginx
Server Hostname:        www.example.com
Server Port:            80

Document Path:          /info_test.php
Document Length:        93219 bytes

Concurrency Level:      200
Time taken for tests:   14.597 seconds
Complete requests:      10000
Failed requests:        1024
   (Connect: 0, Receive: 0, Length: 1024, Exceptions: 0)
Write errors:           0
Total transferred:      939682063 bytes
HTML transferred:       938292127 bytes
Requests per second:    685.07 [#/sec] (mean)
Time per request:       291.940 [ms] (mean)
Time per request:       1.460 [ms] (mean, across all concurrent requests)
Transfer rate:          62866.29 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   19  28.7      3     163
Processing:     4  272 110.6    276     905
Waiting:        1  199  98.3    196     862
Total:          4  290 109.6    293     908

Percentage of the requests served within a certain time (ms)
  50%    293
  66%    337
  75%    362
  80%    379
  90%    426
  95%    463
  98%    489
  99%    533
 100%    908 (longest request)

ApacheとNginxのパフォーマンス検証結果

1位:nginx(woker) + php-fpm ⇒ 685.07 [#/sec]
2位:apache(worker) + php-fpm ⇒ 594.79 [#/sec]
3位:apache(prefork) + php-fpm ⇒ 560.84 [#/sec]
4位:apache(prefork) + mod_php ⇒ 509.72 [#/sec]

上記結果は、環境や利用状況によって異なる場合がありますが、概ね「nginx(woker) + php-fpm」の構成が一番よいパフォーマンスが出ているように見えます。

CakePHP設定サンプル

以下はCakePHPをNginxで利用する際の設定サンプルです。WordPress/Drupalなどの設定も同じような構成になります。catコマンドで変数$が展開されないように「'EOF'」のように囲みます。

注意:fastcgi_paramの設定で、「include fastcgi_params;」を最後の行に挿入した場合、FastCGI設定内容がデフォルト値に上書きされます。

cat > "/etc/nginx/conf.d/default.conf" <<'EOF'
server {
    listen       80;
    server_name  localhost;

    location / {
        root   /var/www/html/app/webroot/;
        index  index.php;
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt)$ {
        access_log off;
    }

    location ~ \.php$ {
        root           /var/www/html/app/webroot/;
        fastcgi_pass   unix:/var/run/php-fpm.sock;
        fastcgi_index  index.php;
        include        fastcgi_params;
        fastcgi_param  REMOTE_ADDR $remote_addr;
        fastcgi_param  REMOTE_PORT $remote_port;
        fastcgi_param  SERVER_ADDR $server_addr;
        fastcgi_param  SERVER_PORT $server_port;
        fastcgi_param  SERVER_NAME $server_name;
        fastcgi_param  CONTENT_TYPE $content_type;
        fastcgi_param  CONTENT_LENGTH $content_length;
        fastcgi_param  QUERY_STRING $query_string;
        fastcgi_param  PATH_INFO  $fastcgi_path_info;
        fastcgi_param  REQUEST_METHOD $request_method;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param  SCRIPT_NAME $fastcgi_script_name;
        fastcgi_param  REQUEST_URI $request_uri;
        fastcgi_param  DOCUMENT_URI $document_uri;
        fastcgi_param  DOCUMENT_ROOT $document_root;
        fastcgi_param  SERVER_PROTOCOL $server_protocol;
        fastcgi_param  GATEWAY_INTERFACE CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE nginx/$nginx_version;
        fastcgi_param  HTTPS $https;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 16k; #4096k total
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
        fastcgi_max_temp_file_size 0; #disable buffering to disk
        client_max_body_size 0; #Allow large uploads
    }
}
EOF

サーバの帯域幅検証(TCPスループット)

この検証は、サーバ2台が必要になります。ローカルでも、広域ネットワークでも検証出来ます。サーバ側でのファイアウォールを解除しておく必要があります。デフォルトのポートは5201です。以下のツールを両方にインストールして確認します。仮にサーバーのIPを「192.168.1.3/192.168.1.4」と設定します。この検証を行うのはAWSまたはVPS環境上にDB接続を行う際、ネットワークにボトルネックがないかを確認するためです。またリバースプロキシサーバーを設定して運用する際に、サーバー単体ではパフォーマンスが出ていても、ネットワークにボトルネックになっていて、パフォーマンスが上がらないケースがあるので、必ず確認してみます。

ym install -y iperf3
192.168.1.3:server

ポートを変更する時には、「-p 8080」のように追加します。

iperf3 -s
192.168.1.4:client

サーバー側のポートがデフォルトポートと異なる場合は「-p 8080」のように追加します。

iperf3 -c 192.168.1.3

結論

近年ネットワークのトラフィックがスマートフォン普及によって急増し、ウェブサーバーを構築・運用する際、最も重要なポイントは、ウェブサーバーのパフォーマンスと安定性ではないかと考えています。ウェブでは、PHP言語が最も多く使われているため、安定的で高性能なウェブサーバが運用できるようなヒントになれば幸いです。

今まで検証してきた内容をまとめると以下のようになります。

  1. サーバーはデフォルトのままのOSは使うな!!
    パフォーマンスチューニングは必ず行うようにします。
  2. PHPは、FastCGI用にシェアドで、「Non Thread Safe」としてビルドする!!
    サーバーの運用が柔軟になり、トラブルが少なく安定的に運用できます。
  3. PHPのSAPIは、php-fpmでFastCGIとして運用する!!
    高負荷でもサーバーがダウンし難くなります。
  4. ウェブサーバーは、Nginxを使う!!
    パフォーマンスの高いサーバーで、FastCGIとの相性が抜群です。
  5. ウェブサーバーはのMPM(Multi-Processing Modules)は、Workerにする!!
    効率のよいサーバーの運用ができます。
  6. ベンチマークは必ず行う!!
    パフォーマンスのボトルネックを理解して運用するのはとても大事です。

※注意:PHPを、apacheモジュールとして、Workerモデルでは運用できません。ApacheをWorkerモデルで運用する際は、必ずFastCGIとしてPHPを構築して運用します。

最後まで長文を読んで頂き ありがとうございました!!