ISUCON7予選敗者が挑むWordPressパフォーマンス・チューニング!
はじめに
GMOペパボ Advent Calendar 2017の9日目の記事です。
2017/10/21(土) ISUCON 2017 予選に参加しました。結果は大敗・・・。前回よりも点数が下がり精神的ダメージは大きかったです。今回はインフラ要素が強い課題となっており、Nginx + PHP-FPMの知識不足で力になれず悔しい思いをしました。
そこで今回はその雪辱を晴らすべく、Nginx + PHP-FPM 7.1 + MySQL 5.7で構築したサーバーで自分のブログをパフォーマンス・チューニングし、どこまで高速化できるか試したいと思います。
お題
- 個人のWordPressを高速化する。目安としてレスポンスタイムとリクエスト毎秒を改善する
ルール
- ISUCONのような特定計算ツールはないので、Gatlingを利用して負荷測定を行う
- 低スペックサーバーを1台を使用。Conohaの1コア/512MB 630円/月プラン。
- Nginx + PHP-FPM 7.1 + MySQL 5.7をインストールし、設定ファイルは基本未修正とするが、最低限WordPressが表示できるようにNginxの調整をする
- 個人の話なので好きにやってよし。
インフラ環境
- サーバー: Conoha 東京リージョン 512Mプラン x 1
- OS: Ubuntu 16.04.3 LTS (Xenial Xerus)
- Nginx 1.10.3 インストール済み&初期設定状態
- PHP-FPM 7.1 インストール済み&初期設定状態
- MySQL Community Server インストール済み&初期設定状態
ということで、やったるぞー!
初期状態で計測
平均リクエスト毎秒は9req/sで、平均レスポンスタイムは244msという結果になった。
5req/s(30s)
13req/s(30s)
Let's パフォーマンス・チューニング!
パフォーマンス・チューニングして、秒間リクエスト数・平均応答時間をどこまで改善できるか試しましょう。チューニングに関しては思いつきで実施しているので順番がご容赦ください。
PHP OPCache を有効
OPCache とは
OPCache とは、コンパイル済みのバイトコードを共有メモリに保存し、PHPがリクエストのたびにスクリプトを読み込み、パースをするのを省くことでパフォーンスを向上させます。
設定方法
PHP-FPMで有効にするには、/etc/php/7.1/fpm/conf.d/10-opcache.ini
に以下を追記することで有効になります。
opcache.enable_cli=1
結果
期待するほど大きな改善にはなりませんでしたが、平均レスポンスタイムが10ms軽減されました。いいですね。
Nginx で静的ファイルのキャッシュ
PageSpeed Insightsにブラウザキャッシュを活用してくださいと指示を受けたので、Nginxによる静的ファイルのキャッシュを有効にしました。
設定方法
/etc/nginx/sites-available/default
のserverディレクティブ内に以下を追加します。
location ~ .*\.(html?|jpe?g|gif|png|css|js|ico|swf|inc) {
expires 7d; # キャッシュ期間は7日
access_log off;
}
結果
PageSpeed Insights の点数は上がりましたが、Gatlingの最小・平均レスポンスタイムは悪化・・・。うーん、なんでだろう・・・。
gzip圧縮の有効
サーバーとブラウザ間のネットワーク帯域を減らすことで高速化を図ります。今回はサーバー側でgzip圧縮をする方式をとるので、CPU負荷があがる欠点もあります。
設定方法
/etc/nginx/nginx.conf
の http
ディレクティブで以下を設定します。
##
# Gzip Settings
##
# gzip 圧縮を有効にする
gzip on;
# Internet Explorer6ではgzip圧縮が正常動作しないので除外する
gzip_disable "msie6";
# ヘッダー情報にVary情報を追記する
gzip_vary on;
# Proxy経由のリクエストでもgzip圧縮を有効にする
gzip_proxied any;
# 1〜9段階ある圧縮レベルの6番目を使用
gzip_comp_level 6;
# gzipで使用するバッファーのサイズを設定
gzip_buffers 16 8k;
# gzipを使用するときのHTTPバージョンを設定
gzip_http_version 1.1;
# gzipの対象となるMIMEを設定
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
結果
全体的に応答速度が改善した。地味に効果あり。
Nginx FastCGIキャッシュの有効
FastCGIとは
ユーザーから要求がある度に、プロセスの生成と破棄が行われます。大量の要求があればその分だけプロセスの生成と破棄が実施され、このことがパフォーマンスの悪化に繋がっていました。
FastCGIとは、プロセスをメモリ上に永続的に起動させたままとすることで、その起動と終了にかかる時間を削減し、結果としてプログラム動作速度の向上およびサーバ負荷の低下が可能となります。
Nginx FastCGI とは
Nginxには Proxy Cache と FastCGI Cacheの2通りがあります。違うについては以下サイトで図解付きで分かりやすく説明されているのでご覧ください。
Nginxを使ったもう一歩進んだWordPressチューニング | cloudrop
FactCGIキャッシュとはPHP-FPMの動的コンテンツをNginxでキャッシュし、PHP-FPMへのアクセスを減らすことでパフォーマンス改善を可能にします。
設定方法
まずは nginx.conf
にNginx全体のキャッシュ設定をします。
##
# Cache
##
# キャッシング時のキーの設定
fastcgi_cache_key "$scheme://$host$request_uri";
# /var/cache/nginx キャッシュを保存するパス
# keys_zone=ゾーン名とゾーンサイズ
# levels=キャッシュディレクトリ配下の文字数(1階層目は1文字、2階層目は2文字という意味)
# inactive=7日後にキャッシュが破棄される
# max_size=キャッシュの最大サイズを設定。これを超えると使用頻度が低いデータから削除される
fastcgi_cache_path /var/cache/nginx keys_zone=czone:10m levels=1:2 inactive=7d max_size=1000m;
変更点が多いので diff
表示としました。変更点のポイントとしては
- WordPress管理画面、RSSフィード、サイトマップなどはキャッシュしない。
- それ以外の処理はキャッシュする
+ set $do_not_cache 0;
+ if ($request_method !~ ^(GET)$) {
+ set $do_not_cache 1;
+ }
+ if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
+ set $do_not_cache 1;
+ }
+ if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
+ set $do_not_cache 1;
+ }
location ~ .*\.(html?|jpe?g|gif|png|css|js|ico|swf|inc) {
expires 7d; # キャッシュ期間は7日
access_log off;
}
location / {
try_files $uri $uri/ @wordpress;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
#include snippets/fastcgi-php.conf;
root /var/www/html;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
include fastcgi_params;
fastcgi_pass unix:/run/php/php7.1-fpm.sock;
+ fastcgi_cache_bypass $do_not_cache;
+ fastcgi_no_cache $do_not_cache;
+ fastcgi_cache czone;
+ fastcgi_cache_valid 200 302 7d;
}
location @wordpress {
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html/index.php;
fastcgi_param PATH_INFO $fastcgi_script_name;
include fastcgi_params;
fastcgi_pass unix:/run/php/php7.1-fpm.sock;
+ fastcgi_cache_bypass $do_not_cache;
+ fastcgi_no_cache $do_not_cache;
+ fastcgi_cache czone;
+ fastcgi_cache_valid 200 302 7d;
}
結果
劇的に改善しました!平均レスポンスタイムも244msから81msと30%になりました。体感的にも早くなったことが感じられます。
PHP-FPM max_children数調整
max_children とは
pm.max_children - the maximum number of children that can be alive at the same time.
「同時に起動することができる子プロセスの最大値」という意味になります。またこの値は、pm の設定によって変化します。pm = dynamicの場合は、作成される子プロセス数になり、staticの場合は子プロセス数となる、パフォーマンスを上げるため固定値でプロセス数を20にしました。
設定方法
-pm = dynamic
+pm = static
-pm.max_children = 5
+pm.max_children = 20
結果
MySQL InnoDBバッファープール
NginxのFastCGIキャッシュに乗ってしまえば、DBアクセスはほぼないので効果は薄いかもしれませんが、念のため設定したいと思います。
InnoDBバッファープール とは
InnoDB は、データとインデックスをメモリーにキャッシュするためのバッファープールと呼ばれるストレージ領域を維持しています。InnoDB バッファープールの仕組みを知り、頻繁にアクセスされるデータをメモリーに維持するためにそれを利用することは、MySQL チューニングの重要な側面です。
とのことで、MySQLのパフォーマンスチューニングの重要な設定項目の一つで、メモリーの80%を割り当てるのが良いとされています。
設定方法
512Mのメモリーのサーバーなので、 /etc/mysql/mysql.conf.d/mysqld.cnf
に以下を設定しました。
innodb_buffer_pool_size=400MB
結果
予想通り変化なし。これは今回のチューニングでは効果が現れないというだけで、基本的には設定すべきです。
PHP7.1 > 7.2 アップグレード
日本では2017/12/01 にPHP7.2がリリースされました。7.1から7.2にアップグレードすることで約10%ほどパフォーマンス改善した内容の記事もありました。基本的にはアップグレードして悪化することはあまりないので、特別な理由がない限りアップグレードすべきです。
結果
前回より応答速度が46%になりました。
パフォーマンス・チューニングの結果
以下の結果になった。平均リクエスト毎秒は21倍に、平均レスポンスタイムは25%と高速化かつ高負荷耐性となった。
- | チューニング前 | チューニング後 |
---|---|---|
平均リクエスト毎秒 | 9req/s | 192req/s |
平均レスポンスタイム | 244ms | 61ms |
150 req/s(30s)
200 req/s(30s)
おわりに
更新頻度の高くない個人ブログだったので、NginxのFastCGIキャッシュを活用することで大幅なパフォーマンス改善ができました。結果的にとても満足しています。しかしこれが更新頻度の高いアプリケーションだとこうはいかなかったでしょう。
さて、これで来年のISUCONに望めるか?というとまだまだです。ISUCON7の課題であったCDNの利用と複数台構成まではできませんでした。次回はそれら課題へ挑戦し、パフォーマンス・チューニング力を磨きたいと思います。
参考
Author And Source
この問題について(ISUCON7予選敗者が挑むWordPressパフォーマンス・チューニング!), 我々は、より多くの情報をここで見つけました https://qiita.com/hypermkt/items/36952405f6f89feb40ca著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .