[技術ブログvol.29] NginxのチューニングとFastCGIcacheの設定

はじめに

[技術ブログvol.25] Nginx + PHP-FPM でWrodPressを動かそうで設定した環境を元にチューニングを行います。

デフォルトの状態よりハイパフォーマンスにチューニングしていきたいと思います。

注意事項

今回はブログ形式のWEBサイトを想定しています。
コーポレートサイトの様なログインせず閲覧されることが多いサイトを想定しています。

ECのプラグイン等を利用したサービスで利用されるような場合は想定していません。
そのようなサイトでご利用になる場合は十分に検証の上ご利用ください。

また、この記事の情報を利用したことに起因するいかななる損害に対しても、ディーネットは責任を負いません。

ご了承の上、あくまで自己責任の範囲においてご利用ください。

実行環境

今回の環境は以下の通りです。
Nginxを除いてCentOS標準レポジトリからyumコマンドでインストールできるものを利用します。

  • OS: CentOS 6.6
  • Nginx 1.6.2
  • PHP 5.3.3
  • MySQL 5.1
  • vsftpd 2.2.2

nginx.confの調整

user  nginx;
worker_processes auto; # 起動するworker Processの数 autoだとCPUのコア数起動する

worker_rlimit_nofile 3072; # nginxユーザのopen filesの調整 worker_connections の3倍程度にしておく

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


events {
# nginxのworkerプロセスの最大コネクション数
# リーバースプロキシとして使ってる場合クライアントだけはなくアプリケーションサーバとのコネクション数も含まれるので注意
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_timeout 65;

# gzipで圧縮
gzip on;

# gzipで返す最低限のプロところるのバージョン
gzip_http_version 1.0;

# gzipで圧縮して返すファイルの種類
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;
# IE6まではgzipで返さない
gzip_disable "MSIE [1-6].";
# Mozilla4はgzipで返さない
gzip_disable "Mozilla/4";
# gzipの圧縮レベル 高くなると容量は圧縮できるがCPUパワーが必要になる
gzip_comp_level 2;
# プロキシ経由での応答も全て圧縮して返す
gzip_proxied any;
# ヘッダーにvary情報をつける
gzip_vary on;
# gzipで使うバッファサイズ
gzip_buffers 4 8k;
# 圧縮するファイルの最小サイズ。これ以下のサイズのファイルは圧縮されない
gzip_min_length 1100;

# fastcgicacheの設定
# キャッシュを保存するパスを指定
# levelsは保存する階層をしてい 深すぎるとinodeが足りなくなるので注意
# keys_zone キャッシュパスのゾーン名とサイズを指定
# inactive で指定した期間アクセスがなければキャッシュが削除される
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=fscgi:10m inactive=10m;
# キャッシュする時のキー情報の指定
fastcgi_cache_key "$scheme://$request_method$host$request_uri";

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

wordpress.confの編集

server {
listen 80;
server_name www.example.com;
root /var/www/html;

index index.php;

access_log /var/log/nginx/www.example.com.access.log main;
error_log /var/log/nginx/www.example.com.error.log error;

# faviconのログは取らない
location = /favicon.ico {
log_not_found off;
access_log off;
}

# robots.txtのログも取らない
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}

# .で始まる隠しファイルへのアクセスは拒否
location ~ /. {
deny all;
}

# URLにuploadsやfilesを含むphpファイルへのアクセスは拒否
location ~* /(?:uploads|files)/.*.php$ {
deny all;
}

# リクエストURIのファイルがあるか探してあれば返す。
# なければindex.phpに引数をつけて返す
location / {
try_files $uri $uri/ /index.php?$args;
}

# wp-adminで終わるリクエストはリライトする
rewrite /wp-admin$ $scheme://$host$uri/ permanent;

## キャッシュするかしないかのフラグ用変数を設定
## キャッシュするなら0
## キャッシュしないなら1をたてる。
set $do_not_cache 0;

## リクエストメソッドがPOSTならキャッシュしない
if ($request_method = POST) {
set $do_not_cache 1;
}

## WPの管理画面にログインしていたりコメント入力者ならキャッシュしない
if ($http_cookie ~ "(wordpress_logged_in_|comment_author_)(.*)") {
set $do_not_cache 1;
}



## 拡張子がphpなファイルの処理
location ~ [^/].php(/|$) {
fastcgi_split_path_info ^(.+?.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}

include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors off;

fastcgi_pass unix:/var/run/php-fpm/wordpress.sock;

## ここからがfastcgi_cacheの設定
## keyzoneを指定
fastcgi_cache fscgi;
# 応答コードが200 302の時は1時間キャッシュ
fastcgi_cache_valid 200 302 1h;
# キャッシュしないフラグがたってるものはそのままバックエンドに流す
fastcgi_cache_bypass $do_not_cache;
# 応答コードが301の場合は1日キャッシュ
fastcgi_cache_valid 301 1d;
# それ以外の応答コードは1分キャッシュ
fastcgi_cache_valid any 1m;
# キャッシュされるまでのリクエスト数。一回リクエストがあればキャッシュ
fastcgi_cache_min_uses 1;
fastcgi_cache_use_stale error timeout invalid_header http_500;
}
}

php-fpmの設定

Nginxとphp-fpmを同じサーバで動かす場合tcpで通信させず
UNIX domain socket で通信させる。
子プロセスの実行ユーザをnginxにする。

cd /etc/php-fpm.d

vim www.conf

 12行目 listen = /var/run/php-fpm/wordpress.sock

39行目 user = nginx

41行目 group = nginx

各サービスの再起動

php-fpmの再起動
service php-fpm restart
nginx の再起動
service nginx restart

WEB確認

http://www.example.com

問題なく見れれば今回はOKです。

FAQ

キャッシュをクリアしたいんだけどどうすればいいの?
/var/cache/nginx/fastcgiのディレクトリの中身を全部消してnginxの再起動
ページ更新したから特定のURLのキャッシュだけ消したいんだけど
デフォルトのnginxではできません。
fastcgi_cache_purgeというサードパーティのモジュールを組み込んでコンパイルする必要があります。
組み込んだあとはserverディレクティブに以下の設定を追記します。

  location ~ /purge(/.*) {
fastcgi_cache_purge fscgi "$scheme://$request_method$host$1";
}
WPのページ更新したらキャッシュクリアするってプラグインあるけど使えるの?
fastcgi_cache_purgeのモジュールを使えばできます。
nginx-proxy-cache-purgeというWPのプラグインでは動作確認できていますが他のプラグインで動くかは検証できません。
WP以外のPHP使ったCMSで使えないの?
今のところ未検証です。
今後検証を行った場合は公開するかもしれません。

ベンチマークの結果

Apacheでのベンチマーク
計測条件
  • OS:CentoS6.6
  • instancetype:c3.large
  • Apache httpd 2.2.3
    • MaxClients等はDefault値
100人が1回リクエストを投げてきた状況をテスト

# ab -c 100 -n 100 http://www.example.com/

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

Document Path: /
Document Length: 16059 bytes

Concurrency Level: 100
Time taken for tests: 15.656 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 1623700 bytes
HTML transferred: 1605900 bytes
Requests per second: 6.39 [#/sec] (mean)
Time per request: 15656.252 [ms] (mean)
Time per request: 156.563 [ms] (mean, across all concurrent requests)
Transfer rate: 101.28 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 1 0.4 1 2
Processing: 1117 11406 5094.9 14047 15653
Waiting: 965 10578 4960.7 12851 15562
Total: 1118 11407 5095.2 14049 15655

Percentage of the requests served within a certain time (ms)
50% 14049
66% 15330
75% 15455
80% 15510
90% 15571
95% 15598
98% 15651
99% 15655
100% 15655 (longest request)

Failed requestsはゼロ。
Requests per second1秒間にいくつのリクエストさばけるかは 6.39
Time per request 1リクエスト当たり何ミリ秒かかってるかは156.563

1000人がそれぞれ1回リクエストを同時に投げてきた時をテスト

# ab -c 1000 -n 1000 http://www.example.com/

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)
apr_socket_recv: Connection reset by peer (104)
Total of 13 requests completed

正常な応答は帰ってこず。

ちょっと値を変えて再テスト
100人が10リクエスト

# ab -c 100 -n 1000 http://www.example.com/

Benchmarking www.example.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


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

Document Path: /
Document Length: 16060 bytes

Concurrency Level: 100
Time taken for tests: 153.707 seconds
Complete requests: 1000
Failed requests: 11
(Connect: 0, Receive: 0, Length: 11, Exceptions: 0)
Write errors: 0
Total transferred: 16237989 bytes
HTML transferred: 16059989 bytes
Requests per second: 6.51 [#/sec] (mean)
Time per request: 15370.711 [ms] (mean)
Time per request: 153.707 [ms] (mean, across all concurrent requests)
Transfer rate: 103.17 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.3 0 2
Processing: 2798 15173 2739.5 14963 88926
Waiting: 2725 13147 2667.2 12916 88904
Total: 2799 15173 2739.6 14963 88927

Percentage of the requests served within a certain time (ms)
50% 14963
66% 15114
75% 15286
80% 15384
90% 16192
95% 17813
98% 18462
99% 18709
100% 88927 (longest request)

Failed requestsが11回既に限界超えてる様子。
Requests per secondTime per requestはさほど変化なし

100人が100リクエストでテスト

# ab -c 100 -n 10000 http://www.example.com/

Finished 10000 requests


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

Document Path: /
Document Length: 16059 bytes

Concurrency Level: 100
Time taken for tests: 1540.935 seconds
Complete requests: 10000
Failed requests: 9960
(Connect: 0, Receive: 0, Length: 9960, Exceptions: 0)
Write errors: 0
Total transferred: 162379962 bytes
HTML transferred: 160599962 bytes
Requests per second: 6.49 [#/sec] (mean)
Time per request: 15409.348 [ms] (mean)
Time per request: 154.093 [ms] (mean, across all concurrent requests)
Transfer rate: 102.91 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 10
Processing: 7326 15386 9255.1 15224 904054
Waiting: 5668 13317 2572.1 13217 260076
Total: 7328 15387 9255.1 15224 904054

Percentage of the requests served within a certain time (ms)
50% 15224
66% 15422
75% 15545
80% 15629
90% 15822
95% 15954
98% 16102
99% 16244
100% 904054 (longest request)

おおよそ10分の1がエラーに。
サーバ側のLAもベンチマーク中100超えた状態に。
本番サーバならAlarmなりまくりの辛いことに。
しかしRequests per secondTime per request:はさほど変化なし

Nginxでのベンチマーク
計測条件
  • OS:CentoS6.6
  • instancetype:c3.large
  • nginx 1.6.2
    • Workerは2
    • worker_connectionsはDefault値
キャッシュしてない状態でのベンチマーク
100人が1回リクエストを投げてきた状況をテスト

# ab -c 100 -n 100 http://www.example.com/

Benchmarking www.example.com (be patient).....done


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

Document Path: /
Document Length: 16059 bytes

Concurrency Level: 100
Time taken for tests: 14.799 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 1626500 bytes
HTML transferred: 1605900 bytes
Requests per second: 6.76 [#/sec] (mean)
Time per request: 14798.706 [ms] (mean)
Time per request: 147.987 [ms] (mean, across all concurrent requests)
Transfer rate: 107.33 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 1 0.3 1 2
Processing: 821 9356 4811.1 10937 14796
Waiting: 712 8859 4710.8 10002 14766
Total: 822 9357 4811.3 10938 14797

Percentage of the requests served within a certain time (ms)
50% 10938
66% 13091
75% 13895
80% 14465
90% 14725
95% 14757
98% 14792
99% 14797
100% 14797 (longest request)

Apacheとかわらず。
ちょっとだけ速い感じの数字だけど誤差の範囲

100人が10回リクエストを投げてきた状況をテスト

# ab -c 100 -n 1000 http://www.example.com/

Benchmarking www.example.com (be patient)
Finished 1000 requests


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

Document Path: /
Document Length: 16059 bytes

Concurrency Level: 100
Time taken for tests: 132.962 seconds
Complete requests: 1000
Failed requests: 2
(Connect: 0, Receive: 0, Length: 2, Exceptions: 0)
Write errors: 0
Total transferred: 16265002 bytes
HTML transferred: 16059002 bytes
Requests per second: 7.52 [#/sec] (mean)
Time per request: 13296.234 [ms] (mean)
Time per request: 132.962 [ms] (mean, across all concurrent requests)
Transfer rate: 119.46 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.4 0 2
Processing: 4254 12881 1773.4 13091 27467
Waiting: 3516 12125 1760.9 12323 26690
Total: 4255 12882 1773.2 13092 27469
ERROR: The median and mean for the initial connection time are more than twice the standard
deviation apart. These results are NOT reliable.

Percentage of the requests served within a certain time (ms)
50% 13092
66% 13297
75% 13450
80% 13556
90% 13790
95% 14151
98% 15378
99% 16980
100% 27469 (longest request)

2回フェイル
Requests per secondとかTime per requestとかはほぼ変わらず

100人が100回リクエストを投げてきた状況をテスト

# ab -c 100 -n 10000 http://www.example.com/

Benchmarking www.example.com (be patient)
Finished 10000 requests

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

Document Path: /
Document Length: 16059 bytes

Concurrency Level: 100
Time taken for tests: 1333.924 seconds
Complete requests: 10000
Failed requests: 33
(Connect: 0, Receive: 0, Length: 33, Exceptions: 0)
Write errors: 0
Total transferred: 162650033 bytes
HTML transferred: 160590033 bytes
Requests per second: 7.50 [#/sec] (mean)
Time per request: 13339.240 [ms] (mean)
Time per request: 133.392 [ms] (mean, across all concurrent requests)
Transfer rate: 119.08 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 7
Processing: 5001 13300 950.8 13270 45939
Waiting: 4293 12531 868.8 12509 30828
Total: 5002 13300 950.8 13270 45939

Percentage of the requests served within a certain time (ms)
50% 13270
66% 13386
75% 13460
80% 13509
90% 13655
95% 13779
98% 13963
99% 14236
100% 45939 (longest request)

33回フェイル

速さはApacheと変化なし。
error率がNginxというかPHP-FRMのほうが低い。

キャッシュ後のベンチマーク

# ab -c 100 -n 100 http://www.example.com/

Benchmarking www.example.com (be patient).....done


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

Document Path: /
Document Length: 16059 bytes

Concurrency Level: 100
Time taken for tests: 0.023 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 1626500 bytes
HTML transferred: 1605900 bytes
Requests per second: 4281.92 [#/sec] (mean)
Time per request: 23.354 [ms] (mean)
Time per request: 0.234 [ms] (mean, across all concurrent requests)
Transfer rate: 68013.14 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 1 0.3 1 2
Processing: 14 19 1.0 19 20
Waiting: 2 9 4.0 10 16
Total: 15 20 1.2 20 22

Percentage of the requests served within a certain time (ms)
50% 20
66% 21
75% 21
80% 21
90% 22
95% 22
98% 22
99% 22
100% 22 (longest request)

Requests per second4281.92
Time per request0.234と1ms以下

100人が10回リクエストを投げてきた状況をテスト

# ab -c 100 -n 1000 http://www.example.com/

Benchmarking www.example.com (be patient)
Finished 1000 requests

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

Document Path: /
Document Length: 16059 bytes

Concurrency Level: 100
Time taken for tests: 0.200 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 16425152 bytes
HTML transferred: 16216680 bytes
Requests per second: 4994.66 [#/sec] (mean)
Time per request: 20.021 [ms] (mean)
Time per request: 0.200 [ms] (mean, across all concurrent requests)
Transfer rate: 80115.21 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 5 2.0 4 12
Processing: 7 15 2.1 15 18
Waiting: 3 8 2.6 8 14
Total: 10 20 1.1 20 22

Percentage of the requests served within a certain time (ms)
50% 20
66% 20
75% 20
80% 20
90% 20
95% 21
98% 21
99% 21
100% 22 (longest request)
100人が100回リクエストを投げてきた状況をテスト

# ab -c 100 -n 10000 http://www.example.com/

Benchmarking www.example.com (be patient)
Finished 10000 requests

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

Document Path: /
Document Length: 16059 bytes

Concurrency Level: 100
Time taken for tests: 1.995 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 163012008 bytes
HTML transferred: 160946240 bytes
Requests per second: 5011.42 [#/sec] (mean)
Time per request: 19.954 [ms] (mean)
Time per request: 0.200 [ms] (mean, across all concurrent requests)
Transfer rate: 79777.44 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 6 1.2 6 13
Processing: 7 14 1.4 13 18
Waiting: 2 7 1.3 7 14
Total: 13 20 0.8 20 24

Percentage of the requests served within a certain time (ms)
50% 20
66% 20
75% 20
80% 20
90% 21
95% 21
98% 22
99% 22
100% 24 (longest request)
1000人がそれぞれ1回リクエストを同時に投げてきた時をテスト

# ab -c 1000 -n 1000 http://www.example.com/

Finished 1000 requests


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

Document Path: /
Document Length: 16059 bytes

Concurrency Level: 1000
Time taken for tests: 3.094 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 16265000 bytes
HTML transferred: 16059000 bytes
Requests per second: 323.23 [#/sec] (mean)
Time per request: 3093.763 [ms] (mean)
Time per request: 3.094 [ms] (mean, across all concurrent requests)
Transfer rate: 5134.13 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 8 13 3.5 12 20
Processing: 92 850 1238.6 122 3064
Waiting: 19 687 1170.6 68 3056
Total: 103 863 1240.3 136 3083

Percentage of the requests served within a certain time (ms)
50% 136
66% 273
75% 338
80% 3053
90% 3069
95% 3077
98% 3082
99% 3082
100% 3083 (longest request)
1000人が同時に10リクエスト投げてきた状況をテスト

# ab -c 1000 -n 10000 http://www.example.com/

Finished 10000 requests


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

Document Path: /
Document Length: 16059 bytes

Concurrency Level: 1000
Time taken for tests: 3.185 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 163171542 bytes
HTML transferred: 161103096 bytes
Requests per second: 3139.81 [#/sec] (mean)
Time per request: 318.491 [ms] (mean)
Time per request: 0.318 [ms] (mean, across all concurrent requests)
Transfer rate: 50031.93 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 9 43 101.1 32 1043
Processing: 1 186 505.4 93 3068
Waiting: 0 120 456.1 43 3062
Total: 94 229 510.2 126 3088

Percentage of the requests served within a certain time (ms)
50% 126
66% 129
75% 130
80% 130
90% 137
95% 429
98% 3060
99% 3074
100% 3088 (longest request)
1000人が同時に100リクエスト投げてきた時を想定してテスト

# ab -c 1000 -n 100000 http://www.example.com/
Finished 100000 requests

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

Document Path: /
Document Length: 16059 bytes

Concurrency Level: 1000
Time taken for tests: 30.605 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 1627924152 bytes
HTML transferred: 1607292840 bytes
Requests per second: 3267.47 [#/sec] (mean)
Time per request: 306.047 [ms] (mean)
Time per request: 0.306 [ms] (mean, across all concurrent requests)
Transfer rate: 51945.30 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 69 216.2 31 3070
Processing: 1 212 767.8 93 21068
Waiting: 0 55 269.9 35 12097
Total: 2 281 805.1 127 21108

Percentage of the requests served within a certain time (ms)
50% 127
66% 160
75% 171
80% 176
90% 424
95% 1129
98% 3384
99% 3846
100% 21108 (longest request)
同時に1万人から1リクエスト投げる想定でテスト

# ab -c 10000 -n 10000 http://www.example.com/

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)
apr_socket_recv: Connection reset by peer (104)
Total of 212 requests completed

こけた・・・。

技術ブログ中の人
キャッシュをうまく使えばより高効率にWEBアクセスをさばくことができますね。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA