Slide 1

Slide 1 text

「魔法少女まどか☆マギカ Magia Exedra」 での負荷試験の実践と学び 悦田 潤哉 2025.07.24 株式会社WFS ©WFS 大規模ソーシャルゲームの安定リリースを支える技術

Slide 2

Slide 2 text

自己紹介 ©WFS 悦田 潤哉(えつだ じゅんや) • 職種 • サーバーサイドエンジニア • 経歴 • シノアリスの運用や新規タイトルの開発を経て 2024年に「魔法少女まどか☆マギカ Magia Exedra」 の開発チームに参画 • リリース前には負荷試験の主幹を担当する 2

Slide 3

Slide 3 text

©2024 Magica Quartet/Aniplex,Magia Exedra Project ©WFS 3

Slide 4

Slide 4 text

©WFS 『魔法少女まどか☆マギカ』シリーズ歴代のシナリオや世界観を追体験! 歴代の魔法少女たちとともに記憶の光を集めながら魔女結界を探索していく ©2024 Magica Quartet/Aniplex,Magia Exedra Project 4

Slide 5

Slide 5 text

負荷試験はなぜ行うか ©WFS 5

Slide 6

Slide 6 text

負荷試験はなぜ行うか ©WFS 6 アクセス集中への備え アプリリリース時には短期間で多数のアクセスが 予想されるため、システムの耐久性を事前確認

Slide 7

Slide 7 text

負荷試験はなぜ行うか ©WFS 7 アクセス集中への備え アプリリリース時には短期間で多数のアクセスが 予想されるため、システムの耐久性を事前確認 ユーザー体験の向上 スムーズなプレイ体験を提供するため レスポンスタイムやエラー率を最適化

Slide 8

Slide 8 text

負荷試験はなぜ行うか ©WFS アクセス集中への備え アプリリリース時には短期間で多数のアクセスが 予想されるため、システムの耐久性を事前確認 ユーザー体験の向上 スムーズなプレイ体験を提供するため レスポンスタイムやエラー率を最適化 ボトルネックの特定 システムの潜在的なボトルネックを特定し リリース後のトラブルを未然に防止 8

Slide 9

Slide 9 text

サーバー構成 ©WFS 内部サービス 国内ユーザー API Requests Cloud Load Balancing アプリケーション層 asia-northeast1 ゲーム API サーバー Kubernetes Engine CDN ゲームアセット Cloud Storage Cloud Armor データ層 asia-northeast1 国内 データベース Cloud Spanner Memcached / Redis Memorystore 海外 データベース Cloud Spanner ゲームログ BigQuery 海外ユーザー API Requests ゲームログtmp Cloud Storage 9 外部サービス GREE common infrastructure 課金管理サーバー (国内) 課金管理サーバー (海外) ログ転送 Fluend

Slide 10

Slide 10 text

内部サービス サーバー構成 ©WFS 国内ユーザー API Requests Cloud Load Balancing アプリケーション層 asia-northeast1 ゲーム API サーバー Kubernetes Engine CDN ゲームアセット Cloud Storage Cloud Armor データ層 asia-northeast1 国内 データベース Cloud Spanner Memcached / Redis Memorystore 海外 データベース Cloud Spanner ゲームログ BigQuery 海外ユーザー API Requests ゲームログtmp Cloud Storage 10 外部サービス GREE common infrastructure 課金管理サーバー (国内) 課金管理サーバー (海外) ログ転送 Fluend CDN

Slide 11

Slide 11 text

内部サービス サーバー構成 ©WFS 国内ユーザー API Requests Cloud Load Balancing アプリケーション層 asia-northeast1 ゲーム API サーバー Kubernetes Engine CDN ゲームアセット Cloud Storage Cloud Armor データ層 asia-northeast1 国内 データベース Cloud Spanner Memcached / Redis Memorystore 海外 データベース Cloud Spanner ゲームログ BigQuery 海外ユーザー API Requests ゲームログtmp Cloud Storage 11 外部サービス GREE common infrastructure 課金管理サーバー (国内) 課金管理サーバー (海外) ログ転送 Fluend CDN

Slide 12

Slide 12 text

内部サービス サーバー構成 ©WFS 国内ユーザー API Requests Cloud Load Balancing アプリケーション層 asia-northeast1 ゲーム API サーバー Kubernetes Engine CDN ゲームアセット Cloud Storage Cloud Armor データ層 asia-northeast1 国内 データベース Cloud Spanner Memcached / Redis Memorystore 海外 データベース Cloud Spanner ゲームログ BigQuery 海外ユーザー API Requests ゲームログtmp Cloud Storage 12 ログ転送 Fluend 外部サービス GREE common infrastructure 課金管理サーバー (国内) 課金管理サーバー (海外) CDN

Slide 13

Slide 13 text

内部サービス サーバー構成 ©WFS 国内ユーザー API Requests Cloud Load Balancing アプリケーション層 asia-northeast1 ゲーム API サーバー Kubernetes Engine CDN ゲームアセット Cloud Storage Cloud Armor データ層 asia-northeast1 国内 データベース Cloud Spanner Memcached / Redis Memorystore 海外 データベース Cloud Spanner ゲームログ BigQuery 海外ユーザー API Requests ゲームログtmp Cloud Storage 13 外部サービス GREE common infrastructure 課金管理サーバー (国内) 課金管理サーバー (海外) ログ転送 Fluend CDN

Slide 14

Slide 14 text

負荷試験の目標値 ©WFS 14 ● スループット ○ 40,000 RPS ● レスポンスタイム ○ 国内 → p50:200ms未満、p99:600ms未満 ○ 海外 → p50:300ms未満、p99:1,000ms未満

Slide 15

Slide 15 text

負荷試験の実施項目 ©WFS 15 1. 性能評価試験 2. 運用オペレーション試験 3. ログ欠損確認試験 4. 持続性確認試験

Slide 16

Slide 16 text

1. 性能評価試験 ©WFS 1. 性能評価試験 目標4万RPSに必要な構成を確認 16

Slide 17

Slide 17 text

17 1. 性能評価試験 - レイテンシ悪化 ©WFS レイテンシが悪化し目標RPSに到達せず

Slide 18

Slide 18 text

18 1. 性能評価試験 - レイテンシ悪化 ©WFS Failed to create session ID: memcached session_start(): Failed to read session data: memcached ● Memcachedの新規セッション作成に失敗 ● Memcachedのアクティブコネクション数が65,000に張り付き 発生したエラー

Slide 19

Slide 19 text

19 1. 性能評価試験 - レイテンシ悪化 ©WFS ● 各Apacheワーカーが独立したコネクションを保持 ● 1度確立したコネクションは解放されない 負荷試験当初はコネクション永続化を有効にしていた コネクション数の計算 ● Pod数 × Apacheワーカー数 = アクティブコネクション数 ● 例:500 Pods × 150 Workers = 75,000 Connections(※上限を超えている)

Slide 20

Slide 20 text

20 1. 性能評価試験 - レイテンシ悪化 ©WFS 2つの解決案を検討 案1:Apacheワーカー数を減らす ● コネクション永続化は維持 ● パフォーマンスへの影響なし ● 最適なワーカー数の調整が必要 ● スケーラビリティに限界あり 案2:コネクション永続化を無効に ● スケーラビリティの確保 ● 変更内容がシンプル ● memcached CPU使用率増加(約20%) ● レスポンスタイムにもごく僅かに影響

Slide 21

Slide 21 text

21 1. 性能評価試験 - レイテンシ悪化 ©WFS 2つの解決案を検討 案1:Apacheワーカー数を減らす ● コネクション永続化は維持 ● パフォーマンスへの影響なし ● 最適なワーカー数の調整が必要 ● スケーラビリティに限界あり 案2:コネクション永続化を無効に ● スケーラビリティの確保 ● 変更内容がシンプル ● memcached CPU使用率増加(約20%) ● レスポンスタイムにもごく僅かに影響

Slide 22

Slide 22 text

22 1. 性能評価試験 - レイテンシ悪化 ©WFS まだ完全には収まっていない

Slide 23

Slide 23 text

23 1. 性能評価試験 - レイテンシ悪化 ©WFS RuntimeException: A session did not become available in the allotted number of attempts. server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting ● Spannerでセッションの取得に失敗 ● Apacheワーカーも連鎖的に枯渇 発生したエラー

Slide 24

Slide 24 text

24 1. 性能評価試験 - レイテンシ悪化 ©WFS トランザクション処理で遅延が発生

Slide 25

Slide 25 text

25 1. 性能評価試験 - レイテンシ悪化 ©WFS プレゼント受け取り処理の問題 問題のあった処理フロー ① Transaction Begin ② アイテム(カード、ゴールド、ゲーム内通貨)を受け取る ③ ゲーム内通貨の場合、外部の課金管理サーバーと通信 ④ Transaction Commit

Slide 26

Slide 26 text

26 1. 性能評価試験 - レイテンシ悪化 ©WFS ① 外部サービスと通信し、ゲーム内通貨を受け取る ② Transaction Begin ③ アイテム(カード、ゴールド)を受け取る ④ Transaction Commit プレゼント受け取り処理の問題 改善後の処理フロー

Slide 27

Slide 27 text

27 1. 性能評価試験 - レイテンシ悪化 ©WFS

Slide 28

Slide 28 text

28 1. 性能評価試験 - 局所的なレイテンシ悪化 ©WFS Pod起動直後のレイテンシが悪い 観測された症状 1.局所的にLBバックエンドレイテンシが 2〜3秒 ほど悪化 2.Pod入れ替わり/スケールアウト直後が特に顕著 3.時間経過とともに改善する傾向

Slide 29

Slide 29 text

29 1. 性能評価試験 - 局所的なレイテンシ悪化 ©WFS マスタデータ取得フロー ① ユーザーからリクエスト受信 ② APCに参照するマスタデータのキャッシュがある場合 APCからデータを返却 ③ APCに参照するマスタデータのキャッシュがない場合 Spannerから該当マスタをSelect Allし、APCにキャッシュ Pod起動直後のマスタデータ取得で遅延

Slide 30

Slide 30 text

30 1. 性能評価試験 - 局所的なレイテンシ悪化 ©WFS ユーザーアクセス前に準備を完了させる postStartフックでマスタデータを事前取得 ● warmup.sh で予め 全マスタデータをSpannerから取得してAPCにキャッシュ ● キャッシュ完了後、healthcheck.html 作成 lifecycle: postStart: exec: command: - /bin/sh - -c - "/app/warmup.sh" readinessProbeとの連携 ● healthcheck.html ファイルの存在確認 readinessProbe: httpGet: path: /healthcheck.html port: 80 Pod起動 マスタデータ キャッシュ完了 readinessProbe 成功 ロードバランサ 追加

Slide 31

Slide 31 text

31 1. 性能評価試験 - TransactionAbort ©WFS 改善 ● 楽観的ロック + 固定値更新 ● リトライ処理の追加 ● 結果:TransactionAbortが12件まで減少(発生率: 0.00012%) UPDATE ItemData SET num = 110 WHERE userId = xxx AND itemMstId = yyy and num = 100; 問題 • 1000万リクエスト中、480件がTransactionAbort(発生率: 0.0048%) • 問題のクエリ例: UPDATE ItemData SET num += 10 WHERE userId = xxx AND itemMstId = yyy;

Slide 32

Slide 32 text

32 1. 性能評価試験 - TransactionAbort ©WFS 分散データベースに最適化した実装へ ● トランザクション保持時間が短縮 ● 楽観的ロックで無駄な競合を回避 ● Spannerの分散特性に適合 改善前 Read-Modify-Writeパターン 1. 読み取り 2. 計算 3. 書き込み 改善後 Read-Writeパターン 1. 読み取り 2. 書き込み

Slide 33

Slide 33 text

2. 運用オペレーション試験 ©WFS 2. 運用オペレーション試験 サービスIN中に実施する運用オペレーションを確認 33

Slide 34

Slide 34 text

34 2. 運用オペレーション試験 - 発生した問題 ©WFS 40,000RPS中のコードデプロイで遅延発生 根本原因 1. kubednsのスケールが APIサーバーのスケールに追いつかない 2. 新Podが名前解決の準備完了前にリクエストを受信 3. 外部サービスへの通信で遅延が顕在化

Slide 35

Slide 35 text

35 2. 運用オペレーション試験 - 発生した問題 ©WFS DNS準備完了を確実に待つ仕組み 対策1: kube-dns-autoscalerの調整 ● coresPerReplica を 256 → 128 に変更 ● より積極的にkubednsをスケールする設定に {"coresPerReplica":256,"nodesPerReplica":16,"preventSinglePointFailure":true} 対策2: postStartのwarmup.sh内に名前解決チェックを追加 [追加] kubernetes.default.svc.cluster.local へ dig 実行し、名前解決成功までリトライ Pod起動 マスタデータ キャッシュ完 了 readinessProbe 成功 ロードバラン サ 追加 DNS準備 完了

Slide 36

Slide 36 text

3. ログ欠損確認試験 ©WFS 3. ログ欠損確認試験 負荷生成中のPod入れ替えによる BigQueryのゲームログ欠損を確認 36

Slide 37

Slide 37 text

37 3. ログ欠損確認試験 - 発生した問題 ©WFS コードデプロイにより、BigQueryのゲームログが欠損 APIサーバー ログ生成 Fluentd ログ収集・転送 CloudStorage ログ一時保存 BigQuery ログ保存 総リクエスト数に対し 0.009%の欠損を確認 根本原因 ● RollingUpdate中、ログ転送前にPod停止 ● Pod停止ギリギリまでリクエスト受信 ● Fluentdバッファの未転送

Slide 38

Slide 38 text

3. ログ欠損確認試験 - 発生した問題 NEG(Network Endpoint Groups)使用時のPod停止フロー 38 ©WFS 経過時間 処理内容 0秒 Pod削除開始 → Endpoint ControllerによりNEGから削除開始 0-14秒 preStopフック実行(sleep 14秒) ※NEGから抜け切るまで新規リクエストは受け付ける 14秒 SIGTERM送信 → Apache/Fluentd shutdown開始 14-30秒 処理中のリクエスト完了待ち Fluentdバッファに未転送のゲームログが残存 ※terminationGracePeriodSeconds: 30秒

Slide 39

Slide 39 text

3. ログ欠損確認試験 - 発生した問題 preStopフックにFluentdバッファの強制転送処理を追加 39 ©WFS # preStop rm -f /var/www/html/healthcheck.html for i in `seq 2` ; do echo flush $i >/proc/1/fd/1; curl http://127.0.0.1:24444/api/plugins.flushBuffers || true sleep 5 done curl http://127.0.0.1:24444/api/plugins.flushBuffers || true sleep 4 echo 'preStop end' >/proc/1/fd/1; ← 念のためヘルスチェックを早期に失敗させる ← fluentdバッファを強制転送

Slide 40

Slide 40 text

3. ログ欠損確認試験 - 発生した問題 コードデプロイによるゲームログ欠損を解消 40 ©WFS 改善前 ● preStop: ● sleep 14秒 ● fluentdバッファ転送: なし ● ログ欠損率: 0.009 % 改善後 ● preStop: ● ヘルスチェックファイル削除 ● sleep 合計14秒 ● flushBuffer ● fluentdバッファ転送: 複数回実行 ● ログ欠損率: 0 %

Slide 41

Slide 41 text

4. 持続性確認試験 ©WFS 4. 持続性確認試験 長時間負荷を流し続け システムの安定性と持続性を確認 41

Slide 42

Slide 42 text

42 4. 持続性確認試験 - 発生した問題 ©WFS GKEノードのディスク使用量が5時間で5%上昇 90 ~ 100時間ほどでディスクフルに

Slide 43

Slide 43 text

43 4. 持続性確認試験 - 発生した問題 ©WFS ディスク使用量増加の原因 ● Fluentdのバッファファイルが各PodのemptyDirに蓄積 ● 高負荷下で生成される大量のゲームログがディスクを圧迫 ● 5時間で 0 → 5.4GB まで肥大化 # ls -lh /var/lib/kubelet/pods/*/volumes/kubernetes.io~empty-dir/tmp/game.log -rw-r--r-- 1 33 33 5.4G 17:04 game.log # df -h | grep /var/lib/kubelet /dev/sda1 95G 11G 83G 13% /var/lib/kubelet

Slide 44

Slide 44 text

44 4. 持続性確認試験 - 発生した問題 ©WFS 対策 ● cronjobで24時間ごとにrollout restart を実施 ● Pod切り替えによりemptyDirを含むディスクをリセット 定期的なPod再起動による解決 副次的な効果 ● メモリリークの予防 ● APCのリフレッシュ ● 日々積み上がるリソースを定期的にクリーン

Slide 45

Slide 45 text

全ての試験項目をクリア ©WFS 45 1. 性能評価試験 2. 運用オペレーション試験 3. ログ欠損確認試験 4. 持続性確認試験

Slide 46

Slide 46 text

まとめ ©WFS 負荷試験は運用リハーサル 性能測定だけでは見逃す問題がある 計画性と実施期間の重要性 46

Slide 47

Slide 47 text

ご清聴ありがとうございました ©WFS

Slide 48

Slide 48 text

WFSセッション一覧 WFSはCEDEC 2025で全8セッション登壇いたします ©2024 Magica Quartet/Aniplex,Magia Exedra Project ©WFS ©WFS Developed by WRIGHT FLYER STUDIOS © VISUAL ARTS/Key 7/22 第4会場 13:40-14:40 レギュラーセッション LLM翻訳ツールの開発と 海外のお客様対応等への社内導入事例 郡司 匡弘 / 松井 望 / 小野 幸人 BP 7/23 第1会場 09:30-10:30 レギュラーセッション ヘブンバーンズレッドにおける、 世界観を活かしたミニゲーム企画の作り 方 菊岡 大夢 GD 7/23 第1会場 10:50-11:50 レギュラーセッション ヘブンバーンズレッドの レンダリングパイプライン刷新 野口 顕弘 ENG 7/23 第2会場 13:20-14:20 レギュラーセッション 「魔法少女まどか☆マギカ Magia Exedra」の グローバル展開を支える、開発チームと翻訳チームの 「意識しない協創」を実現するローカライズシステム 原田 大志 / 篠原 功 PRD 7/23 第2会場 13:20-14:20 レギュラーセッション 「魔法少女まどか☆マギカ Magia Exedra」 の必殺技演出を徹底解剖! -キャラクターの魅力を最大限にファンに届けるためのこだわり- 新谷 雄輝 / 金子 俊太朗 / 佐々木 文哉 VA 7/24 第5会場 15:00-15:25 ショートセッション ライブサービスゲームQAのパフォーマ ンス検証による品質改善の取り組み 小野 粋哉 / 勅使川原 大輔 BP 7/24 第5会場 18:00-18:25 ショートセッション ヒューリスティック評価を用いた ゲームQA実践事例 山本 幸寛 PRD 7/24 第8会場 18:00-18:25 ショートセッション 「魔法少女まどか☆マギカ Magia Exedra」での負荷試験の実践と学び 悦田 潤哉 ENG