CentOS6にPHP7を導入してWordPressを高速化する

サイトの高速化を色々と検証した結果、まずはPHPのアップデートを行うことにしました。
CentOS6のPHPは5.3なのでPHP7まで上げれば3倍のスピードになるはず。

1.アップデートの目的

PHP7導入の目的はWordPress高速化が主な目的ですが、メモリ使用量削減もかなり魅力的。
また十分に高速化できるようなら、WordPress Super Cacheの利用を中止しようと思います。WordPress Super Cacheはアクセスするタイミングによってはモバイルサイトがキャッシュされてしまうので、PCでアクセスしたときに表示がおかしい時があるんですよね。

2.アップデート要件

今回のアップデートの要件です。

  1. 運用性を考慮してyumでアップデートする。
  2. ダウンタイムを最小限にする。なるべくmuninのグラフに影響が出ないようにする。
  3. 効果がなければ元に戻す。

phpは環境に合わせてコンパイルする方がパッケージを使うより速いらしいのですが、phpのアップデートに気付くのが遅れると脆弱性対策が遅くなる可能性があります。なるべく手間をかけずに運用したいのでyum&nightly yumで自動アップデートできるようにします。
そのためにはCentOS公式レポジトリより信頼性の劣るremiレポジトリを使う必要がありますが、実際どれくらい劣るのかは分からないので自分で使って勉強してみます。

3.事前準備

まずは現在のサーバにインストールされているPHP5.3関係のパッケージを調べます。PHP5.3→PHP7へアップデートするとパッケージの依存関係で失敗するらしいので、アンインストール→インストールを実施するための準備です。

# yum list installed |grep php
php.x86_64                          5.3.3-46.el6_7.1                   @updates 
php-bcmath.x86_64                   5.3.3-46.el6_7.1                   @updates 
php-cli.x86_64                      5.3.3-46.el6_7.1                   @updates 
php-common.x86_64                   5.3.3-46.el6_7.1                   @updates 
php-gd.x86_64                       5.3.3-46.el6_7.1                   @updates 
php-mbstring.x86_64                 5.3.3-46.el6_7.1                   @updates 
php-mcrypt.x86_64                   5.3.3-4.el6                        @epel    
php-mysql.x86_64                    5.3.3-46.el6_7.1                   @updates 
php-pdo.x86_64                      5.3.3-46.el6_7.1                   @updates 
php-pear.noarch                     1:1.9.4-4.el6                      @base    
php-pecl-apc.x86_64                 3.1.9-2.el6                        @base    
php-php-gettext.noarch              1.0.11-12.el6                      @epel    
php-process.x86_64                  5.3.3-46.el6_7.1                   @updates 
php-tcpdf.noarch                    6.2.11-1.el6                       @epel    
php-tcpdf-dejavu-sans-fonts.noarch  6.2.11-1.el6                       @epel    
php-tidy.x86_64                     5.3.3-46.el6_7.1                   @updates 
php-xml.x86_64                      5.3.3-46.el6_7.1                   @updates 
phpMyAdmin.noarch                   4.0.10.15-1.el6                    @epel

次にyumPHP7をインストールするための準備。
php7が含まれているremiレポジトリとremiに必要なepelレポジトリをインストールします。

# yum -y install epel-release

## remiレポジトリのrpmファイルをダウンロード
# wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

## remiレポジトリをインストール
# rpm -Uvh remi-release-6.rpm

インストール完了後に/etc/yum.repos.d/を確認すると、remi.repoの他にremi-php70.repoというファイルが増えています。ファイル名の通りこれがphp7用のremiレポジトリです。

# ls  /etc/yum.repos.d/
CentOS-Base.repo       CentOS-Media.repo  epel-testing.repo
CentOS-CR.repo         CentOS-SCL.repo    remi-php70.repo
CentOS-Debuginfo.repo  CentOS-Vault.repo  remi.repo
CentOS-fasttrack.repo  epel.repo          remi-safe.repo
4.PHP5.3をアンインストール

remiレポジトリの準備ができたので現行のphp5.3をアンインストールします。

# yum -y remove php php-bcmath php-cli php-common php-gd php-mbstring php-mcrypt php-mysql php-pdo php-pear.noarch php-pecl-apc php-php-gettext.noarch php-process php-tcpdf.noarch php-tcpdf-dejavu-sans-fonts.noarch php-tidy php-xml phpMyAdmin.noarch
5.PHP7をインストール

php5.3のアンインストールが終わったらすぐにphp7のインストールを行います。
インストールするphpモジュールは「3.事前準備」で調べたphpモジュールと、APCに変わるPHPアクセラレータのZend OPcache+APCuの二つ。

そういえばPHP7対応のphpMyAdminはremi-php70レポジトリに含まれていないためこのままではインストールできません。remi-testを有効化するとインストールできるようですが、最近phpMyAdminを利用しなくなったのでまずはインストールしないことにします。

# yum --enablerepo=remi-php70 install php php-bcmath php-cli php-common php-gd php-mbstring php-mcrypt php-mysql php-pdo php-pear.noarch php-pecl-apc php-php-gettext.noarch php-process php-tcpdf.noarch php-tcpdf-dejavu-sans-fonts.noarch php-tidy php-xml php-opcache

PHP7のインストールが完了したらひとまずphp -vでバージョンを調べます。

# php -v
PHP 7.0.4 (cli) (built: Mar  2 2016 18:11:33) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies

php7インストールが成功しました。OPcacheもバッチリ導入されています。

6.PHP7の初期設定

phpの最低限の設定と、PHP/OPcache/APCuのメモリ使用量を設定します。
最低限のプラグインしか利用していないので、メモリ使用量を低めに抑えておきます。

# vi /etc/php.ini
## PHPの最大メモリ使用量を128MB→64MBに縮小
- memory_limit = 128M
+ memory_limit = 64M

## Timezoneを明示的に設定
- ;date.timezone =
+ date.timezone = "Asia/Tokyo"

# vi /etc/php.d/10-opcache.ini
; The OPcache shared memory storage size.

## OPcacheの最大メモリ使用量を128MB → 36MBに縮小
- opcache.memory_consumption=128
+ opcache.memory_consumption=36

# vi /etc/php.d/40-apcu.ini
; The size of each shared memory segment, with M/G suffixe
## APCuの最大メモリ使用量を32MB → 4MBに縮小
- ;apc.shm_size=32M
+ apc.shm_size=4M
7.apache+PHP7を起動し効果を確認

設定変更が終わったらhttpdを再起動してapacheにPHP7を読み込ませ、WordPressの応答時間を確認します。
httping_resp2_riscascape_net-day
PHP7への切り替えは月曜0:00に実施しましたが、グラフにノイズは出ていませんね。要件2の「ダウンタイムを最小限にする」は成功したようです。

数値を見てみるとPHP5.3で240ms程度かかっていたWordPressの処理がPHP7になってからは70ms程度に減り、約3倍に高速化されました。SSLと合わせた応答時間も330ms程度から170msに約倍速化しています。

PHPメモリ使用量を確認してみます。apacheをpreforkモードで動作している場合は、PHPのメモリ使用量はapacheに含まれます。
httpd-day
PHP5.3で520MB程度だったメモリ使用量がPHP7では350MBに減少しています。apacheは10プロセスに固定しているので1プロセス17MB減ったことになります。
このグラフではわかりませんがメモリリークも減っているように見えます。これならapacheのプロセス数を増やしても大丈夫かも。

WordPressの体感速度も確実に向上していました。
PHP5.3(キャッシュ無効)はページ遷移に一瞬待たされる感じがしましたが、PHP7(キャッシュ無効)だと瞬間的に切り替わる感じで違和感がありません。
PHP5.3(キャッシュ有効)よりは遅いはずですが体感速度はほとんどかわりません。そういえばGoogleの「PageSpeed Insights」は応答時間が200msを超えると「遅い」と診断しているので、200msが体感速度上の壁なのかもしれません。

8.OpcacheとAPCuのGUIコンソールを導入する

最後にOPcacheとAPCuのGUIコンソールを導入してキャッシュ使用率を確認できるようにします。どちらもパッケージには含まれていないので有志の方が作成しGitHubで公開しているスクリプトを利用しました。

A one-page opcache status page
https://github.com/rlerdorf/opcache-status

# wget https://raw.githubusercontent.com/rlerdorf/opcache-status/master/opcache.php
# mv opcache.php /var/www/html/

a_one-page_opcache_status_page
APCu – APC User Cache
https://github.com/krakjoe/apcu/

# wget https://raw.githubusercontent.com/krakjoe/apcu/master/apc.php
# mv apc.php /var/www/html/

apcu_apc_user_cache

PHP7へのアップデートは大正解でした。良い結果が出たのでWordPress Super Cache利用中止を決断できました。しばらくはこの環境で運用しようと思います。