OpenWork Tech Blog

社員クチコミサービスを運営しているオープンワークエンジニアによるテックブログです。

php8.1, Symfony5.4, Aurora MySQL3に更新しました

Symfonyエラー画面の右上にいるやつ(のつもり)

はじめに

弊社では定期的にFWのメジャーバージョンアップを実施しています。
これまで、以下のような対応を行ってきました。

今回、php7.4のEOL対応を起点に、古い機能をまとめてバージョンアップしたので、内容を残したいと思います。
つらつらと書きましたが、伝えたいことは以下です。

  • メジャーバージョンアップを定期的に実施している
  • 課題に向き合い、少しずつ改善を重ねている

今回の対応内容

言語 before after
php 7.4 8.1
Symfony 4.4 5.4
Aurora MySQL 1 3
Redis 2.8 6.2
Vue.js 2 3(移行ビルド)

弊社の技術スタック全体は、以下の記事をご参照ください。

techblog.openwork.co.jp

規模感は大体こんな感じです。

  • 期間:2022/09〜2023/01
  • 人数:初期は2,3名、最後の1ヶ月は15名前後
  • ソースコード:php全体で7000ファイル、50万行程度
  • 修正差分:下図のような感じでした

バージョンアップ手順

環境構築

2020年の対応でコンテナ化されており、ローカルのDockerで試行錯誤できるので、インフラメンバー以外でも手がつけやすい状態でした。
ベースイメージはAmazonLinuxを利用していますが、検討開始時点では公式でphp8.1対応しておらず、やむを得ずremi版を利用していました。(2022年末に公式対応されたので、滑り込みで置き換えた)

テストコードを通す

サーバサイドは、満足とは言えないまでもそれなりの量が存在しているため、テストが通るようになればそれなりに動くようになります。
フロントエンドのテストは、かろうじてSelenium WebdriverによるE2Eテストが存在したので一定検知できましたが、その後はもぐら叩きのように修正を入れることになりました。

スルーテスト

カバレッジが高くても自動テストですべての動作は保証されないので、人によるテストは一定必要になります。どこまでテストすべきかは議論がありますが、今回は例年に倣いホワイトボックステストを予定していました。
Webアプリエンジニア全員のリソースを効率的に使うために、最低限画面を見れば分かるような操作によるエラーが起きないよう、簡単なスルーテストを行いました。テストカバレッジが低い機能から順に検証することで、未知の不具合が終盤に出てくるリスクを低減しました。

ホワイトボックステスト

スプレッドシートに機能をリストアップし、担当チームを割り振って検証を進めました。 機能のリストアップは、Controller/Commandの一覧を出力できるSymfonyのコマンドを利用しています。
基本的にはFatControllerや時間のかかるコマンドなど、検証が難しい機能から始めることを推奨しました。

負荷検証

k6cloudを利用し、大量アクセスを模擬しました。
アプリケーションサーバの応答速度や負荷については問題ないことが確認できましたが、データベースが高負荷になっていることがわかりました。
解決策としては、以下を試すことにしました。

  • PerformanceInsightから負荷の高いクエリを抽出
  • パラメータ調整
  • SQLの改善

データベースパラメータに関する知見が少なく、パラメータ調整については他社事例を見てとりあえず試してみるくらいしか行っていません。結局、SQLの効率化による負荷低減を図りました。
すべてのクエリを調べきるのは不可能なので、問題が起きたら都度対応するという判断で負荷検証をOKとしました。

負荷検証イメージ(単位は伏せますが、主に秒間リクエスト数と応答速度を確認しました)

リリース後のセッション継続確認

過去の事例として、リリース直後にユーザセッションが切れる不具合が起きているため、大きな修正が入る場合は確認を行っています。特にFWバージョンアップの際は注意したほうが良いと思います。
余談ですが、SPAやCookieなどを利用した機能にて、サーバ側が後方互換のない修正を入れるとエラーになるケースもよくある例かと思います。

起きた問題

設定不備による部分的なDB接続失敗

テストでしか利用しない設定があり、この設定が本番だけ空欄になっていたのですが、Doctrineがバージョンアップされたことにより、全体的に設定が読み込めなくなっていたようです。
Auroraインスタンスの変更もありメンテナンス状態にしていたため、ユーザ影響はありませんでしたが、最後の最後にまだ出るか...と。

大量IN句指定によるクエリの長時間化

Aurora3(MySQL8)で発生する問題のようです。 パラメータ調整またはIN句に指定する値を分割することで修正対応を進めています。

過度なログ出力によるコマンドのメモリエラー

バッチ処理のループ内で大量のWarningログが発生しており、ログが滞留した結果エラーとなっていました。

今後の課題

今回、シニアエンジニア2名(インフラ知見あり)が主担当を務めましたが、おそらく再現性はありません。今後、もう少しハードルを下げられないか、楽にできないか、という視点で課題解決に取り組んでいきます。
また、今回は間に合わないと判断し、暫定対応でしのいだ部分もあるため、次回のメジャーバージョンアップまでに計画的に対応していく必要があります。

ステージング環境と本番環境の差分解消

本番のみ異なる設定がなされていたり、本番でしか動かない機能があり、不具合の事前検知が難しい状況が一部存在します。本当に必要な差分なのか改めて確認し、なるべく差分を無くせるよう検討を進めます。
また、開発環境のデータベースがしばらく更新されていない状態だったため、データ量起因の不具合にも気づきにくくなっていました。(ステージング環境は週に一度本番に近いデータに更新されますが、開発環境は不定期。)
データ更新を必要な手順としてドキュメントに残しておくことで、ひとまずの対応とします。

パイプライン修正

ビルド中にもDB接続失敗によるエラーが起きていたのですが、そのままパイプラインが継続しデプロイまでされていました。本来であれば、エラーを検知した時点でパイプラインを止めたほうが良いはずです。

バージョンアップ対応の早期化、分散化

対応が大変だった要因は、やはり直前にまとめて対応してしまったことだと思います。 全体に関わる修正は検証が難しいですが、少しずつライブラリ更新やDeprecationコードの修正をすすめることにより、メジャーバージョンアップ時の負担を軽減することができるはずです。(修正量の面でも影響範囲の面でも)
また、全体リソースの効率化につながるとの考えで、例年インフラ更新とアプリケーション更新を同時に行っていますが、これも可能なら分けたほうが良いように感じています。検証時は機能開発を止めることになるので各所との調整が必要ですが、本当に同時にバージョンアップすべきかは気にしておきたい所です。

リリース方法の改善

現在、切り戻しのために再度リリースを行う必要があり、不具合が判明してから復旧までに10分以上かかってしまっています。
また、

  • 簡単なスキーマ変更にも人が介在している
  • 色々なサービスとの連携で仕組みが複雑化しており、保守が難しい

といった問題も指摘されていることから、リリースパイプラインの再設計を検討しています。

参考:現在のリリースの仕組み

techblog.openwork.co.jp

さいごにいつもの

(phpではありますが)モダンな環境で開発したい方、開発者体験の向上に興味がある方、ぜひお話しましょう。

www.openwork.co.jp