はじめに
こんにちは!GameWithのサーバサイドエンジニアのkuromokaと、神崎です!
今月約1年かけて進めていた、GameWithのPHP7.3へのバージョンアップが完了しました!GameWithはリリースから5年以上PHP5系で運用されていましたが、ようやくPHP7.3にすることができました。
今回のブログでは、このバージョンアップを行うにあたっての具体的な作業内容やバージョンアップ前と後でのパフォーマンス比較などについてお話します。
実はPHP Conference 2019に同様のテーマでセッションの申込みをしたのですが、残念ながら不採用だったためブログ形式にしました。
チーム構成
バージョンアップ作業は途中の入れ替わりなどありつつ、おおよそ以下のような5人チームでした。
- サーバサイドエンジニア:2人
- インフラエンジニア:1人
- ディレクター:1人
- チームリーダー:1人
バージョンアップ前のシステム構成
- PHP5.6
- FuelPHP 1.6
- Ubuntu 14.04
バージョンアップ後のシステム構成
- PHP7.3
- FuelPHP 1.6(魔改造)
- Ubuntu 18.04
FuelPHPについては、バージョンアップ中は最新のPHP7系には対応していなかったため、既存の1.6を魔改造をして対応させました。
なぜPHP7にあげようとしたか?
以下のような理由で、PHP7へのバージョンアップを決めました。
PHP5.6のセキュリティサポートが2018年12月末までのため
長年の機能追加によりパフォーマンスが低下し、サービスが不安定になる状態が頻発するようになっていた。そのためPHP7にすることでパフォーマンスが向上して、サービスの安定稼働が見込めると考えたため
PHP7のバージョンアップまでのスケジュール
2018年10月にPHP7バージョンアップチームを結成しました。結成当初はサーバサイドエンジニアとインフラエンジニアの2人体制でスキマ時間に取り組んでいましたが、他チームとの兼任で他の作業が忙しかったこともあり、思うように作業が進みませんでした。
そこで2019年1月頃に入社をした私たち2人が2019年4月頃にバージョンアップチームにJOINすることになり、週に最低1日はバージョンアップチームとしての作業を行う時間を確保してもらうようにしました。
その後は順調に作業が進められるようになり、2019年9月に全ての作業が完了しました。
PHP7の作業方針
タスクの管理は、GitHubのProjectsを利用しカンバンスタイルで管理しました。
ソースの管理は、リポジトリから新規ブランチを切って、そのブランチのコードをPHP5.6並びにPHP7.3両方に互換性のある書き方に修正する形で作業を進めました。
理由として、GameWithで動いているサーバ(WEBサーバ・管理画面サーバ・デプロイサーバなど)のソースコードは既存のリリースフローの都合上、基本的にすべて同じリポジトリかつ同じブランチのため、ソースコードもすべて同じになるためです。
PHP7.3のみに対応したコードを書いてしてしまうと「PHP7.3のサーバでは動くけどPHP5.6のサーバでは動かない」といった状態が発生する可能性があり、各サーバごとに段階的にバージョンアップを進めることができなくなります。そのため上記の方法で作業を進めました。
具体的な作業内容
PHP5.6からPHP7.3の変更点の列挙
https://www.php.net/manual/ja/migration70.php https://www.php.net/manual/ja/migration71.php https://www.php.net/manual/ja/migration72.php https://www.php.net/manual/ja/migration73.php
まずは公式の移行マニュアルをすべて読み、変更点を列挙しました。
エラーの修正
初めはUnitテストで起きたエラーの修正を行いました。
その後、integrityというソフトや、Seleniumで動かしているE2Eテストで起きたエラーを修正しました。
sort系関数の変更
PHP7からソートアルゴリズムが変わったため、sort系の関数の結果がPHP5と同じ順番になるような互換関数を作りました。ソートアルゴリズム変更の影響を受けそうな利用箇所については、作った互換関数に置き換えてテストコードで同じ並び順が保証されるようにしました。 https://www.php.net/manual/ja/migration70.incompatible.php#migration70.incompatible.other.sort-order
インフラ作業
今回バージョンアップに伴い、インスタンスを新しく作り直しました。古いインスタンス(c4)のPHPのバージョンアップをあげることもできましたが、コストパフォーマンスの良いインスタンス(c5)を利用したかったため作り直すことにしました。
本番でWEBサーバを置き換えるときは最初1台だけPHP7にしたインスタンスをELBに紐付けて、問題がないことを確認してから残りのインスタンスも入れ替えるような方法を取りました。
リリース後に起きた問題点
以下のような対応漏れがいくつか発生しましたが、幸いサービスが止まったり見えなくなるような事態はありませんでした。
- sort系関数の対応漏れ
- foreachの挙動変更の対応漏れ
- 数値形式ではない文字列で演算をしている箇所の対応漏れ
感想
以前までは多いときに1日3回ほどサービスが止まることもありましたが、PHP7.3へバージョンアップしたことでほぼ発生しなくなりサービスの安定稼働を実現できるようになりました。また、パフォーマンス向上によって起動するサーバの台数を減らせたり、コストパフォーマンスの良いインスタンスを利用できるようになったため、運用コストを大幅に削減することができました。
作業中はUnitテストやE2Eテストで既存の動作を担保できたのは大きい点で、心理的安全性が高い状態で作業ができました。
入社して2,3ヶ月後にバージョンチームにJOINをしたので、ドメイン知識が少なかったりシステムが複雑だっため構成の把握に苦労したこともありました。幸いリーダーのドメイン知識が高かったのでバージョンアップをやりきる事ができました。
バージョンアップ前と後でのパフォーマンス比較
GameWithは毎回サーバでHTMLをレンダリングしているため、今回のバージョンアップのパフォーマンス影響がダイレクトにでました。
Auditsのスコアや、Latency・CPU使用率が大幅に改善されました!
今後の展望
- PHP7の新機能の利用
- インスタンスのスペックのさらなる最適化
- サーバ台数のさらなる最適化
- PHP7.4にバージョンアップ!?
最後に
まだまだ書ききれなかったエピソードがたくさんあるので、良かったらもくもく会などで会いに来てください!
GameWithのDeveloper向けTwitterアカウントを開設しました。
もくもく会の告知やブログの更新情報などを発信するので良かったらフォロー宜しくお願いします!