SREチームの金澤です。
PHP5.3→5.6バージョンアップが完了しましたので報告いたします。
CakePHP1.3→2.8バージョンアップが完了してから約2カ月での移行となりました。
2019/03/20にコネヒトさんで開催されたPHP勉強会で、その詳細について発表させていただきました。
(このときは管理画面、バッチサーバーまで移行完了していました)
PHPのバージョンアップ自体は3月中に完了していましたが、その後関連ライブラリのバージョンアップも併せて行いました。
バージョンアップに向けたCI改善
2019/2/5にCakePHP1.3→2.8バージョンアップが完了し、その後すぐにCI周りの改善に取り掛かりました。
その詳細をPHP5.6化に向けたCircleCIのアップデートにまとめています。
目的は以下の2点です。
- PHP5.6の文法に対応する
- @PSR2を設定
- @PHP56Migrationを設定
- CIでUTを回す
- UTが通らなければマージできないようにする
※PHP5.6との互換性を検証したく@PHP56Migrationを設定しましたが、これはあまり活躍しませんでした。
(PHP-CS-Fixerの@PHP56MigrationはPow関数の対応しかサポートされていないようです)
https://mlocati.github.io/php-cs-fixer-configurator/?version=2.2
PHP5.6バージョンアップ準備
PEARライブラリのコード管理
ランサーズは一部の機能にPEARライブラリを利用しています。
新規にサーバーをAnsibleで構築するにあたり、pear installでインストールしていました。
しかし、pear installでインストールすると/usr/share/srcに配置されるため、ライブラリ管理がOS側に依存していました。
2019/1にpear.php.netが数週間停止する事態が起きたこともあり、php.pear.netに依存しないサーバー構築手順に変更しました。
利用していたPEARライブラリは以下2つです。
- Math Stats
- Vendorディレクトリに直接配置
- Crypt Browfish
- Composerで管理
Crypt Browfishは依存関係があり、単純にVendorディレクトリに配置するだけでは動作しないため、
composer.jsonに以下のように記述して管理するようにしました。
"repositories": [ { "type": "vcs", "url": "git@github.com:pear/Crypt_Blowfish.git" } ], "require": { "pear/crypt_blowfish": "dev-master#8a56b74", }
※これらのライブラリはPHP7に対応していないので、代替手段を用意しておきたいところです。
AWS SDK PHPをV2に統一
AWS SDKについては、V2をメインに利用していましたが、S3関連の処理だけV1を利用していました。
AWS SDK V1はPHP5.6の環境ではStrict Warningを出してしまうため、すべてV2に統一しました。
PHP5.6コンテナの構築と切り替え
まず開発用コンテナのPHP5.6化から始めました。
ランサーズの開発環境はDockerを利用しており、docker-compose.ymlには以下のように記述しております。
version: '2' services: app: image: xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/lancers_app:latest hostname: app networks: lancers: ipv4_address: 10.100.6.11 extra_hosts: - "dev.lancers.jp:10.100.50.11" … container_name: app-6-11 volumes: - ~/www:/var/www
PHP5.3環境とPHP5.6環境をすぐに切り替えられるようにしました。
構築したPHP5.6のコンテナはタグ名を5.6とし、docker-compose.override.ymlを以下のように記述します。
version: '2' services: app: image: xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/lancers_app:5.6
PHP5.6で稼働させたい場合は、このdocker-compose.override.ymlを配置して
$ docker-compose up -d
とすれば、PHP5.6コンテナにすぐに切り替わります。
PHP5.3コンテナに戻したい場合は、imageの行を#でコメントアウトし、再度
$ docker-compose up -d
とすれば戻ります。
PHP5.6対応
以前PHP5.6コンテナに切り替えて検証したときには、
CakePHP1.3とAWS PHP SDK V1のソースが大量のStrict Warningを出していました。
今回、CakePHP2.8とAWS PHP SDK V2にそれぞれバージョンアップして臨んだのですが、
まだStrict Warningを出している箇所が残っていました。
親クラスと子クラスの引数を合わせる
一番多かったのは、親クラスと子クラスの引数が一致していないパターンです。
PHP5.3では警告されませんでしたが、PHP5.6では以下の警告が出力されます。
Strict Standards: Declaration of WorkTask::afterSave()
should be compatible with Model::afterSave($options = Array)
例えば、この例では、WorkTask::afterSave関数の引数が以下のように定義されているのに対し、
public function afterSave($created)
親クラスのModel.phpでは、以下のように定義されていました。
public function afterSave($created, $options = array())
CakePHP1.3→2.8にバージョンアップした過程で引数の仕様変更があったためです。
以下のソースの子クラス全関数の引数をチェックし、親クラスと引数を一致させるように修正しました。
- Model.php
- Behavior.php
- Controller.php
- Component.php
参照を引数に取る関数の対応
PHP5.4からの仕様変更。
例えば、以下のコードで
$key = array_shift(array_keys($data));
以下の警告が出力されます
Strict (2048): Only variables should be passed by reference
参照を引数にとる関数は一度変数に格納する必要がありました。
$keys = array_keys($data); $key = array_shift($keys);
参照が戻り値の関数の対応
PHP5.4からの仕様変更。
PHP5.3で戻り値を参照として受け取っていると
$Db =& ConnectionManager::getDataSource($model->useDbConfig);
以下の警告が出力されます
Strict (2048): Only variables should be assigned by reference
これは実体のまま受け取るように修正して対応しました。
$Db = ConnectionManager::getDataSource($model->useDbConfig);
初期化せずにオブジェクトとみなして代入
PHP5.6では以下のようにいきなり代入すると、
$record->type = 'type1’;
以下の警告が出力されます
Warning Error: Creating default object from empty value in ...
オブジェクトのメンバ変数を初期化する場合は、まずオブジェクト自体の初期化が必要です。
※入れ子の場合でも初期化が必要
$record = new stdclass(); $record->type = 'type1'; $record->fields = new stdclass(); $record->fields->key = 'key1';
PHP5.6化後のパフォーマンス
サーバーレスポンス
移行前に160ms前後であったものが140ms前後に改善。
アクセラレータがAPC → APCu + OPCacheになりましたが、その効果が出ていると推測しています。
バッチの実行時間
最も時間がかかっていた7時間のバッチが、30分ほど短縮されました。
全体的には、約1.13倍程度のパフォーマンスアップになりました。
関連ライブラリのバージョンアップ
PHP5.6化に伴い、composerで管理している各種ライブラリのバージョンアップも行いました。
詳細は別途ブログに書きたいと思います。
バージョンアップ資料の共有
PHP5.6バージョンアップ手順の詳細をGithubで公開しました。
https://github.com/LancersDevTeam/PHP_versionup
今更感はありますが、今後、移行する方の参考になりましたら幸いです。
今後の予定
ランサーズのPHP、CakePHPバージョンアップは、以下のフェーズに分けて取り組んでいます。
Apache + mod_php + PHP 5.3 + CakePHP 1.3
↓(第1フェーズ)
Nginx + PHP-FPM + PHP 5.3 + CakePHP 1.3
↓(第2フェーズ)
Nginx + PHP-FPM + PHP 5.3 + CakePHP 2.8
↓(第3フェーズ)
Nginx + PHP-FPM + PHP 5.6 + CakePHP 2.8
↓(第4フェーズ)
Nginx + PHP-FPM + PHP 5.6 + CakePHP 2.10
↓(第5フェーズ)
Nginx + PHP-FPM + PHP 7.x + CakePHP 2.10
今回、第3フェーズを終えることができました。
続きまして、第4フェーズである、CakePHP2.10化に着手いたします。
これが終われば、いよいよPHP7化に着手できます。
PHP5.6もすでにセキュリティサポートが切れていますのでできるだけ早くPHP7化に着手したいところです。