はじめに
AWS SUMMMIT TOKYOの3日目で一番印象に残ったセッションのレポートです。 ロマサガ世代にはたまりません!!
登壇者
- 株式会社アカツキ エンジニア 駒井氏(@e__koma)
- VTuberの管理やってます!
ゲームシステムの特性
- トラフィック量の増減
- お昼の時間帯が多い
- イベントをすると前日の2倍のアクセスが来る
- 最大ピークが読みづらい
- スケールするシステムが求められる
- 今の所ダウンしていない
ロマサガRSとは
- 23年ぶりの完全新作
- ロマサガ3から300年後の世界が舞台
- リリース1ヶ月後で1千万ダウンロード!!
アーキテクチャ編
全体像
- スマホ
- ALB
- お知らせサーバ
- ゲームのお知らせ通知用
- ゲームサーバ
- ダメージ計算などロジックを司るサーバ
- ECS
- Nginx
- fluentd
- elixir
- プレイヤーデータ
- Aurora
- Session/cache
- ElastiCache
- memcache
- ElastiCache
- 認証サーバ
- 認証データ
- DynamoDB
- 認証データ
- お知らせサーバ
- ALB
構成要素
- サーバサイドの言語はElixir
- 並列性が高い
- 高速
- 50msでほぼすべての処理が終わる
- 詳細は別資料SpeakerDeck speakerdeck.com
- インフラ構成管理
- 99%をCloudFormationで管理
- 環境変更のミスは0件
- SSMの秘匿情報は手動。
- kumogata/kumogata2でコード管理
- Rubyのラッパーツール
- 条件分岐などのコードが書ける
- 開発環境だけシングル構成にする
- 秘匿情報を環境変数化してSSMから取得など
- プロセス構成管理
- 100%Docker運用
- 構成管理するプロセスは全てDocker化
- デプロイが安定する
- デプロイ・スケーリングトラブルはリリース後1度もない
- デプロイしているものと同じImageをローカルで起動
- オーケストレーションはECS
- EKSはまだ東京GAでなかった
- Fargateは?
- サーバレス、簡単にスケールする
- スケール時間がEC2とあまり変わらず(昔はもっと遅かった)
- ロギング(当時はCloudWatchLogs一択だった)
- フィルタリングが弱い
- Insertコストが高い
- EC2/ECSに戻した
- 100%Docker運用
- ロギング
- CloudWatchLogs
- エラーのみフィルタしたログ
- Datadlog Logs
- エラーのみフィルタしたミドルウェアログ
- S3
- アクセスログ
- Athenaで分析
- CloudWatchLogs
- 監視
- CloudWatch
- Datadog
- 99%をCloudFormationで管理
分析
- 行動ログ
- Redashで可視化
負荷対策編
負荷テスト事例
- 心得
- 負荷テストと改善フェーズは必ず確保する
- ギリギリでやると間に合わない可能性がある
- テスト毎の目的・ゴールを設定する
- 負荷テストをシて負荷を確認することが目的ではない
- 負荷テストと改善フェーズは必ず確保する
- ツール
- Locustを採用
- Python出掛ける
- Response結果をParse、計算
- 複雑なシナリオも簡単に書ける
- Docker化して1コマンドでスケール
- さらっと10000res/sとか出せる
- Locustを採用
負荷テスト
- 単性能テスト
- APMで分析&改善
- Datadog APM
- N+1クエリ検出
- 低負荷でOK
- Datadog APM
- APMで分析&改善
- 過負荷テスト
- 各コンポーネントに過負荷を書ける
- EC2にだけ
- RDSにだけ
- ボトルネック、エラーになる箇所、原因を特定して修正
- 例)EC2のCPU 使用率70%位からエラーが出始める
- どこかのパラメータの成約に引っかかってないか?
- チューニングする
- OSカーネル?
- DBパラメータ?
- チューニングする
- どこかのパラメータの成約に引っかかってないか?
- 例)EC2のCPU 使用率70%位からエラーが出始める
- 各コンポーネントに過負荷を書ける
- 高負荷テスト
- スケールアウトの確認
- リソースが分散されるか
- シナリオごとの負荷特性を確認
- リセマラシナリオ
- PlayerをCreateする処理
- リセマラシナリオ
- システムサイジング
- スケールアウトの確認
- 障害テスト
- 1部のコンポーネントに意図的に障害を起こして、サービスが継続するか確認する
- 例)負荷テスト中にAuroraをフェイルオーバする
- ClusterEndpointのDNS切り替えが未完了時に再接続すると、Reader側のDNSをキャッシュしてしまう
- 期待値はWriter側を見てほしいため、エラーが出続ける
- ClusterEndpointのDNS切り替えが未完了時に再接続すると、Reader側のDNSをキャッシュしてしまう
- 例)負荷テスト中にAuroraをフェイルオーバする
- 1部のコンポーネントに意図的に障害を起こして、サービスが継続するか確認する
- 長時間テスト
- 一晩中高負荷をかける
- メモリリークやfd枯渇など検知できる可能性
- RDS CPU使用量
- 負荷をかけ続けることで右肩上がり
- どこかにO(N)がある?スロークエリの懸念
- 負荷をかけ続けることで右肩上がり
- RDS CPU使用量
- メモリリークやfd枯渇など検知できる可能性
- 一晩中高負荷をかける
- 負荷テストのPDCAを高速化する工夫
- すばやくスケールする負荷テストツール
- Player資産を付与するデバッグAPI
- Player資産がないとN+1も検知しづらい
- 何度でも壊して作り治せるインフラ(CloudFormation)
- メトリクス監視のCloudWatchダッシュボード
- やったからこそ発見できた問題
- N+1問題
- DBパラメータ上限
- 長時間不可によるスロークエリ検知
- 巨大Responseによるネットワーク帯域圧迫
- リリース後
- 100%のAZ
ECSスケーリングの工夫
ECS AutoScalingの課題
- スケールアウト
- EC2リソースが用意されていることが前提
- Lambdaを使って制御している
- 1ECSにつき1EC2の前提
- AutoScalingのDesired Capacityをみて、ECSのDesiredと一致させる
- 1ECSにつき1EC2の前提
- Lambdaを使って制御している
- EC2リソースが用意されていることが前提
- スケールイン
- 停止するEC2とECSタスクが一致する保証がない
- ライフサイクルフックを設定しておく
- EC2のインスタンスIDを取得
- コンテナインスタンスをDRAININGする
- 完了まで待つ
- ECSタスクの停止
- 停止するEC2とECSタスクが一致する保証がない
工夫
- AlarmだけでECSScaling
- スケールアウト時間は2分強
運用の工夫編
デリバリーパイプライン
- Github
- CodeBuild(並列性が高い。従量課金)
- 1日100ビルド。月100ドルいかないくらい。(Mediumで運用)
- ECR
- CodeBuild(並列性が高い。従量課金)
サーバレスバッチ
- CodeBuildをバッチサーバとして利用
- ビルド・コンパイル済みのアプリケーションを再利用可能
- プロビジョニングに30~40秒余計な時間はかかる
- 例
- アイテムドロップのシュミレータ
- DB並列マイグレーション
- 10分×並列数
自動復旧
- 入門 監視にも記載がある
- リカバリ例
- 月に1回起きるメモリリーク対策
- DATADOG
- SNS
- Lambda
- どのEC2で起きているかを特定
- ECS
- DRAININGしてリカバーする
- Lambda
- Slack
- Lambda
- DRAININGしてリカバーする
- ECS
- どのEC2で起きているかを特定
- Lambda
- SNS
- AuroraのDNS切り替え対策
- Aurora
- SNS
- Lambda
- ECS
- ローリングアップデート
- Lambda
- Slack
- Lambda
- ローリングアップデート
- ECS
- Lambda
- SNS
- Aurora
まとめ
非常に実践的な内容で、参考になるセッションでした。自分の担当プロダクトがまさにこれから負荷試験に突入しそうなフェーズであるため、このセッションで学んだことを参考にして実践してみたいと思います! 子育て中なのでゲームをやる余裕はまったくないのですが、ロマサガRSは・・・ダウンロードしたくなりました・・・。