本記事は オルトプラス Advent Calendar 2023 の12/23の記事です。
はじめに
こんにちは、オルトプラスでテックリードをしております濱野と申します。
社内のプロジェクトではエンジニアのリーダーをやりつつ、Unityエンジニアの採用担当もさせていただいてます。
今回はスマホ向けゲームのプロジェクトでサーバー運用費を下げるために実施したことを紹介します。
本記事では下記のようなプロジェクトやサービスを対象としています。
- リリース初期段階ではなく、運用してからしばらく経過しているプロジェクト
- AWSの下記サービスを利用していてこれらのサービスのコストダウンしていきたい
- Amazon EC2、Amazon RDS、Amazon CloudFront
また、コードレベルではなくざっくりしたご説明となりますのでそちらはご容赦ください。
対応方針と対策内容について
まずは対応方針については下記の通りに定めました。
リリースしてからしばらく経過していたため既に遊んでいただいているユーザーさんのプレイ感を極力変えないようにしています。
- プレイ感やプレイサイクルが変わらないようにする
- プレイ感:ゲームの操作方法、UI、画面遷移の待ち時間など
- プレイサイクル:ログインボーナスの受け取り日時、イベント開催期間など
- 運用/保守のメンテナンス作業が少なくなるように自動化していく
上記の対応方針を踏まえて対策内容についても下記の通りに定めました。
常時コストが発生しているデータ通信量削減、インスタンスタイプ変更、サーバー台数増減による対策に重きを置いています。
- Amazon EC2
- API通信(GET/POST)でのリクエスト負荷軽減
- メモリ使用量を削減
- 最適なインスタンスタイプへの変更
- AutoScalingの導入
- Amazon RDS
- プロビジョンドインスタンスからServerless v2への移行
- Amazon CloudFront
- 未使用リソースを初回ダウンロードしないように除外
以降で具体的な対策について記載しています。
Amazon EC2 対策内容
API通信(GET/POST)でのリクエスト負荷軽減
主に「ユーザーデータが関連するAPI」に対策を入れました。
ガチャ一覧取得のAPIなど「日時によって更新されるデータ」はアプリ側の時間管理が必要となり工数が膨れ上がるため保留にしています。
- ログイン時or画面遷移時にアプリの表示に必要なユーザーデータを一度だけ一括取得(GET)する
- 「データの追加、変更、削除」のいずれかが発生した時だけ差分をPOSTする
- レスポンスは差分データのみサーバーからアプリ側に返却する
⇒ 毎回全件返却するとデータの整形(json化)に処理時間も掛かるので避ける
メモリ使用量削減の対策
- リリース初期の未使用になったマスタデータを削除
⇒ 例えばリリース1年間のガチャデータなど、
DBのレコードにマスタのIDが保存されている場合は該当レコードも削除する。 - サーバーのプロセスで使用しないマスタデータはキャッシュしないように変更
⇒ アプリで使用するマスタデータはS3経由でダウンロードする。
最適なインスタンスタイプへ変更
API対策とメモリ使用量で削減出来た分を考慮してインスタンスファミリーやサイズを選定します。
- メモリに余裕がある場合:「c6i.4xlarge」 → 「c6i.2xlarge」
- メモリに余裕がない場合:「c6i.4xlarge」 → 「r6i.2xlarge」など
AutoScalingの導入
- 予定されたアクションでスケールイン/スケールアウトを設定
- ピークタイム:サーバー台数を追加 (夕方〜深夜帯の時間帯)
- オフピークタイム:サーバー台数を減少 (深夜帯~夕方の時間帯)
- 動的ポリシーを設定
- 「CPU使用率」と「ターゲット毎のリクエスト数」の2つのしきい値を設定
Amazon RDS
プロビジョンドインスタンスからServerless v2への移行
対策前はプロビジョンドインスタンス(r6gシリーズなど)を利用していましたが、
- EC2のAPI(POST)対策によってDBへのアクセス数が減少
- 深夜帯〜夕方までのリクエスト数が比較的少なめ
という稼働状況でServerless v2の方がコストを抑えられる傾向だったので切り替えました。
スケーリングが優秀なのでACUは2〜128のような設定で稼働させています。
ただ、メンテ明けなど瞬時にリクエストが増加するタイミングはスケーリングが間に合わないため、事前に最小ACUを高めに設定してからサービスを開けるようにしています。
Amazon CloudFront
未使用リソースを初回ダウンロードしないように除外
こちらは難しい対策はしておらず概要だけのご説明となります。
前置きとして、アプリで使用しているリソースファイル(画像など)はUnityのAssetBundle(※addressableではない)を使用しておりS3にアップロードしてCloudFront経由でアプリからダウンロードしています。
ゲームアプリでよくある初回起動時に「何GBのリソースをダウンロードします」みたいなリソースダウンロードが発生しますが、こちらのリソースを放置していると運用が長くなるにつれて肥大化していくため定期的に下記のような対策を取っています。
- 初回リソースダウンロードの対象となるファイル一覧を定義しているjsonファイルから、使用しなくなったイベント画像などを除外する
- リソースを管理しているフォルダまたはファイルの末尾にイベントIDを付けるなどルール化しておき、特定のIDの範囲内は除外するスクリプトファイルを用意する
- Unityのバージョンアップデートによってフルビルドは極力実施しないようにする
- Unity2019LTSで作成したAssetBundleはUnity2022LTSでも互換性があるため、メジャーバージョンのアップデートがあったとしても互換性がある限りは更新だけをビルドするようにしています
まとめ
今回のコスト削減の実施結果は下記の通りとなりました。
- EC2とRDSのサーバー稼働費は月単位で15%〜20%ほどのコスト削減(前年比)
- CloudFrontは1ユーザー当たり400MB削減 (1.5GB→1.1GB)
特にEC2とRDSのアクセス数が少ない時間帯に低稼働させてるだけでも効果が見込めました。運用中のプロジェクトだと現在の負荷状況が読みやすいかと思いますので参考になりましたら幸いです。