はじめに
医療系クラウドサービスを提供している会社で働いている2kaiです。
2022年7月に入ってから新型コロナウイルス感染爆発に伴い、患者及び医療スタッフの利用数が急増し、ピーク時間帯のデータベースCPU使用率がWriter、Reader共に監視の閾値を度々超えてくるという状態になりました。
と、思った次の日には100%に届くスパイクまで発生したために、急遽サービス無停止でスケールアップを実施しました。
現時点での月間アクセス数は1億リクエストを超えるくらいです(正確には感染爆発の前月の集計値になります)。
作業時間帯(22時頃)のアクセス数は850/min。
システム概要
Ruby on Rails in awsで構成された、恐らく一般的なモノリスアプリケーションです。
- アプリケーションはWeb、Worker、Batchから構成
- Ruby on Railsで実装し、WriterとReaderに負荷分散するようにコーディング
- 各アプリケーションはElastic Beanstalkで管理
- データベースはAurora MySQLで、WriterとReader × 2で構成
- データベースは常時稼働(オートスケールしない)
- ElastiCache for Redisを利用(今回は関係無し)
作業
作業は単純に画面ポチポチで終わります。
- Readerのスケールアップ
- Writerのスケールアップ
- Writerの入れ替え
- アプリサーバの再起動
Readerのスケールアップ
インスタンスを選択して「変更」ボタンから「インスタンス設定」内の「DB インスタンスクラス」を変更します。
夜間に作業したのでWriter1台でも全てのアクセスを捌けるかなとも思いましたが、念のため平行作業せずに1台ずつ順次変更。
一瞬接続が切れCan't connect to MySQL server on xxxx…
やMysql2::Error::ConnectionError: MySQL server has gone away
が発生しましたが、すぐに回復しました(1秒とかそういうレベル)。
Writerのスケールアップ
Reader同様に「変更」から設定変更します。
Writerの場合は最初にフェールオーバーが実行され、Readerに降格後スケールアップが実行されます。
フェールオーバー時にMysql2::Error::ConnectionError: Lost connection to MySQL server during query
が発生しました。
ダウンタイム(今回は10~15秒程度でした)は、DBのサイズやアクセス数等によって変わると思うので注意が必要です。
アプリサーバを再起動
Webアプリは問題ありませんでしたが、WorkerアプリでThe MySQL server is running with the --read-only option so it cannot execute this ...
が発生しました。元writerだったインスタンスへのコネクションがプールされている様子が見受けられます。
Workerのアプリサーバを再起動して回復しました。
Elastic Beanstalkでは以下で再起動できます。Deploy設定をローリングにしておけばダウンタイムは発生しません。
Writerの入れ替え
降格してReaderになった元Writerのインスタンスを、再度昇格してWriterに戻しておきます。
モニタリングのメトリクスに一貫性がなくなる為です CloudWatchのメトリクスはロール(writer,reader)で見るので気にする必要は無いけど、各インスタンスをグラフで見る時は識別子で認識する事が多いので利便性を考えると戻しておいた方が良さそうです。
Workerアプリの再起動も忘れずに実施。
おわりに
作業直後にSQLのタイムアウトが発生する事がありました。
DBキャッシュが全てクリアされた為と思われます。
今回は夜間だった事もあり悲惨な事にならずにすみました(あわてて主要テーブルにマニュアルでクエリを投げておきましたが、本来はMySQLの機能として暖機するようですので杞憂だったかも)。
データ量が多くなってくるとキャッシュが充分に生成の時間も長くなると思いますので注意が必要ですね。
今後
Aurora Serverless v2も出てきた事ですし、そろそろDBもオートスケール実装したいなと思っています。
アプリ側もお世話になったElastic Beanstalkを卒業して、コンテナサーバーレスへの移行を計画しています。
追記 2022/7/29
前職の後輩からInsufficientInstanceCapacityエラーが発生すると最悪Readerインスタンス減る可能性あるから、変更じゃなくて追加/削除でやった方が良いんじゃないかとご指摘頂きました。
うん、たしかにそうかもと思いました。同様の作業をする方は検討してみてください。