大規模トラフィックにどのように備えて
負荷対策を実施しているのか?
株式会社ミクシィ
モンスト事業本部 開発室 室長
白川裕介
自己紹介
自己紹介
- 氏名
- 白川裕介
- 経歴
- 2012年に新卒でミクシィに入社。
- SNS「mixi」でアドネットワークを担当したのちXFLAGのアドテクスタジオへ異動
- その後、モンストの開発に携わりマネージャーを経験
- 現在では開発室の室長として、モンストに関わるエンジニア組織を統括
モンスターストライク
モンスターストライク
自分のモンスターを引っ張って弾き、敵のモンスターに当てて倒していくという、スマートフォンの特性を活用した、
誰でも簡単に楽しめるアクションRPGです。ゲームはターン制をとっており、
一緒にいる友だちと最大4人まで同時に遊べる協力プレイ(マルチプレイ)が特長です。
2013年の10月の提供開始から現在※までの世界累計利用者数5,100万人を突破
※ 2019年07月時点
「世界累計利用者数 5,100万人を突破したスマホアプリ」
モンストドリームカンパニー
「モンパニ」は、最大4人同時に遊べる協力プレイ(マルチプレイ)で、
家族や友だちとわいわい盛り上がることのできるカジュアルな「ひっぱりすごろくゲーム」です。
スマホアプリ「モンスターストライク」でおなじみのキャラクターたちが、
それぞれの特徴や能力を活かした職業に就いた姿で活躍する公式スピンオフゲームです。
「モンスト公式スピンオフゲーム ゆるっとワイワイ!ひっぱりすごろく!」
アジェンダ
モンストを支えるシステム
アーキテクチャ構成
負荷対策について
2018年末に向けて実施した内容
2019年末に向けて実施している内容
まとめ
・
・
・
・
・
・
モンストを支えるシステム
利用中のシステム
• クライアント
• 開発言語: C++
• ゲームエンジン: Cocos2d-x
• サーバー
• 開発言語: Ruby
• フレームワーク: Padrino
• デプロイツール: Capistrano
• 自動化ツール: Chef, Ansible, Terraform
監視システム
• Nagios
• サーバー監視
• kibana
• ログ可視化
• CloudForecast
• リソースのモニタリング
• Grafana
• APIリクエストなどをモニタリング
アーキテクチャ構成
アーキテクチャ構成
LB
App
App
App
DB(master) DB(backup)
Redis
Memcached
Batch
Turn
アーキテクチャ構成
LB
App
App
App
App
• ロードバランサー
• A10を利用し配下に約200台のAppサーバーを配置
• Appサーバー
• マルチクラウドで計算リソースの確保
• AWS / GCP / IBM を利用
• オンプレサーバーも利用
• ハイブリット構成にしている理由
• 単一点障害の回避
• 在庫の確保の柔軟性
アーキテクチャ構成
DB(master) DB(backup)
DB
• 全てオンプレサーバーで構成
• 約300台稼働中
• 複数拠点・複数系統でサーバー故障に備える
• DBサーバーへのアプローチ
• 水平分割 / 垂直分割
• Indexやクエリの最適化
• 高性能なマシンを投入 (高いIO性能を出せるもの)
• IOMemory / NVMeを利用
DBサーバー障害への対策
• データが完全に消失しないように何重にも防衛
• DCレベルでの冗長化
• DBサーバーは2拠点での冗長化
• DC毎に複数系統に冗長化
• master - backup構成
• 定期的にDBのSnapshotをとりクラウド上に保存
• 数週間分のbinlogのBackupを保持
アーキテクチャ構成
Redis
Memcached
Batch
Redis / Batch / memcached
• Redis / Batch
• Resqueを利用した非同期処理
• ミッションの達成判定や報酬付与などを非同期処理で実施
• memcached
• すべてオンプレサーバーで構成
• DBサーバーとの距離を重視
• DB性能限界へのアプローチとしてCacheを用いる
• モンストではCacheの比重が大きい
• app <=> memcached の往復が100回を超えるAPIもある
• Cacheを利用することによりレスポンスの高速化を実現
• Replica Poolを用意しサーバー障害へ対策
アーキテクチャ構成
Turn
マルチを実現している技術について
• Turnとは
• Traversal Using Relays around NAT (TURN)
• RFC5766
• http://tools.ietf.org/html/rfc5766
• 「NAT超え」を可能にするための技術
• ホスト/ゲスト間の通信はTurnサーバーを介してパケットをリレー
• Turnサーバーを経由することによりNATを超えた通信を実現
• モンスターストライクのリアルタイム通信を支える技術
• https://speakerdeck.com/genkami/monsutasutoraikufalseriarutaimutong-xin-wozhi-eruji-shu
アーキテクチャ構成まとめ その1
• 稼働中のサーバーはトータルで約1,000台
• DBサーバー: 約300台、Appサーバー: 約200台
• Turnサーバーを利用しマルチプレイを実現
• パケットのリレーを行う用途
• Cacheを多用することでレスポンスの高速化
• モンストではmemecachedを利用
• Resqueを利用した非同期処理
• バックエンドはRedis
アーキテクチャ構成まとめ その2
• ハイブリッド構成
• 自社DCのオンプレサーバーとクラウドサーバーの併用
• 単一点障害の回避や柔軟な在庫の確保
• サーバー障害に対して、何重もの対策を実施
• DCの冗長構成
• 2つDCを利用しDCレベルでの冗長化を実現
• memcachedのReplica Poolの用意
負荷対策について
モンストにおける負荷対策
• ピーク時のトラフィックに耐えうる準備
• イベント型のゲームという特性上、ユーザのアクセスが偏る
• 平常時とピーク時でトラフィックは数倍から数十倍の差
モンストにおける負荷対策
• ピーク時のトラフィックに耐えうる準備
• イベント型のゲームという特性上、ユーザのアクセスが偏る
• 平常時とピーク時でトラフィックは数倍から数十倍の差
モンストにおける負荷対策
• アクセスの増大が予想されるタイミング
• コラボ開始のタイミング
• コラボ限定のガチャやクエストが開始
• 限定クエストが開催されるタイミング
• 高難易度のクエストなど
• 限定アイテムが配布やキャンペーン開始タイミング
• 最近のイベントだと 「30連以上確定アゲインガチャ」
• 対応
• Appサーバーのスケールアウト
• 事前に負荷が想定されるDBをスケールアップ / スケールアウト
Appサーバーの負荷対策
• Appサーバーをスケールアウト
• モンストではAppサーバーをCPUのコア数換算で試算
• 1コアあたりUnicornのworker数を1としている
• 例: 64コアのマシンならworker数は64となるように設定
• Appサーバーが増えると同時に処理できるリクエストの数が増加
• デメリット
• DBへのアクセスも増えるためDBへの負荷が増加
• 通信量が増えるためネットワークのトラフィックが増加
• 台数を多く並べれば並べるほどよいというわけではない
DBサーバーの負荷対策
• スケールアップ
• 負荷が高くなりそうなDBサーバーを高性能なマシンに入れ替え
• IOMemory / NVMe (高いIO性能を出せるもの)
• スケールアウト
• 垂直分割(vertical partitioning)
• 一部のテーブルを別のDBへ移動
• 水平分割 (horizontal partitioning)
• 1つのテーブルの各行を別々のテーブルへ分散
• モンストではシャーディングを用いて実施
シャーディング
• シャーディングとは?
• 特定のアルゴリズムに従いデータを複数のDBに分散させる手法
• その結果DBへのアクセスを分散させることが可能
• モンストにおけるシャーディングを用いた負荷分散手法
• https://speakerdeck.com/haman29/bcu-30-server-9
昨年の年末について
年末年始のモンスト
• 年越しと共にアクセスが急増しピークを迎える
• 主に0時から始まる新ガチャがメイン
• 年越しのタイミングでログイン処理が急増
• そしてガチャが回される
• 負荷の傾向
• APIリクエストが滞留
• データベースでslowクエリが多発
• 膨大なリクエストを捌き切ることができない
2018年の年末に向けての取り組み
• 2017年は緊急メンテは未実施とはいえ
• 快適なサービスの提供はできていない
• 振り返るともっとやれたことはあった
• 2018年はやれることは全部やる
• やっておけばよかったという後悔はしない
• これまで負荷対策としては実施しなかったアプリケーションの最適化
• クライアントエンジニアも負荷対策に巻き込む
2018年の年末に向けて
• アプリケーションからのアプローチ
• クライアント / サーバー双方からのアプローチ
• インフラからのアプローチ
• 年末に向けて機器調達や回線増強
• サーバー機器のスケールアップ
• これまでの負荷対策のメイン
• これまでの年末年始の結果
• 2016年はサーバー負荷による緊急メンテを実施
• 2017年は2時間程度アクセスが重い状況
アプリケーションからのアプローチ
アプリケーションからのアプローチ
• ピーク時はログインで詰まる
• 年越しでログインするユーザが急増
• 年越しのタイミングでユーザはタイトルに戻る
• タイトルに戻らなくてもゲーム内の表示は更新されるのだが
• ログイン時に走るリクエストはモンスト内でも負荷が高いものが多い
• ボトルネック部分を見つけ出し対処する箇所を決定
• ログイン時のフローを大幅に改修
• ログイン時に必要なAPIを高速化
これまでの傾向からこれら2つを対応することに決定
アプリケーションからのアプローチ
1. ログイン時のフロー大幅に改修
• モンストはログイン時(ゲーム起動時)にデータを一気に取得
• 起動後の画面遷移等を早くするため
• ログイン時の処理はリリースから5年間積み上がっている
• 改修はほとんど実施されていない
• 今回はログイン時のフローに手を入れる
アプリケーションからのアプローチ
• 現状のログイン時のフローを整理から始める
• ログイン時に必要なAPIの数
• アプリ起動からホーム画面への遷移で13回もAPIリクエストが発生
• 13回のリクエストがすべて成功した場合のみOK
• 1つでも失敗すると最初からやりなおし
アプリケーションからのアプローチ
• 結果
• ログイン時に必要ないAPIの呼び出しをやめる
• ログイン時に13本必要だったAPIを3本にまとめる
• 効果
• 高負荷時のログイン成功確率が増加
• APIリクエスト数が減るので成功確率も上がる
• また通常時もログイン失敗する確率が激減
• 必要なネットワーク帯域が減少
• 一方でログイン時の処理が遅くなるデメリット
• これまでは13本のリクエストを並列実行していた
アプリケーションからのアプローチ
2. App timeの長いAPIを高速化
• ログイン時に必要なAPIで致命的に遅いものが存在
• 高負荷時には指数関数的に遅くなる
• そのAPIの名は deck/get
• ユーザの所持しているキャラクターを全部取得する
• 最大で約5,000体所持可能
• モンストでは起動時にユーザの所持するモンスターを再取得
アプリケーションからのアプローチ
• キャラクターに付随する情報を全所有キャラで検索
• 1ユーザで最大5体のみ所持可能な情報
• 多くても100体程度しか保持していない情報
• 対応
• 事前に付加情報を持つキャラリストを作成し保持
• 取得した全キャラクターと照らし合わせてつなぎ合わせる
アプリケーションからのアプローチ
• リリース後の効果
アプリケーションからのアプローチ
• リリース後の効果
インフラからのアプローチ
インフラからのアプローチ
• 通常時のappサーバー
• CPUコア数換算で12,000core
• モンストのシステム構成はmemcachedを多用
• memcachedはすべて自社DCのサーバーで運用
• 1つのリクエストで何度もサーバー間の通信が発生
• 自社DCとの物理的距離が大きく影響
• クラウド事業者の選定ではレイテンシーを最重要視
• 複数のクラウド事業者を利用
• 柔軟なリソースの確保が可能
• 障害発生時のリカバリーが可能
インフラからのアプローチ
• Appサーバーの増強がメイン
• リソースの状況
• オンプレサーバーの増強
• DBやmemcachedとの距離が最短
• クラウドサーバーのリソース確保
• 自社DCとの距離が比較的近い IBM/GCPなど
• ネットワーク帯域の増強
• 各クラウド事業者と弊社DCとの間の専用回線
• 対応
• 年末に向けては 26,000コア を目標
• max connectionの上限近くまで確保
インフラからのアプローチ
• オンプレサーバーの本番投入時
インフラからのアプローチ
• オンプレサーバーの本番投入時
結果
結果(2019年を迎えて)
• 緊急メンテ
• なし
• レスポンス状況
• 0時から15分程度、動作が重たくなる
• 前年の2時間と比べると大幅な解消
結果(2019年を迎えて)
2019年末に向けて
2019年の年末に向けて
• さらなるAPIの高速化に向けて
• フレンド一覧の取得の改善
• ログイン時に必要な情報だけに絞る
• フレンドに付随するユーザデータ
• フレンドの助っ人キャラ一覧など
• 必要なタイミングで必要な情報を取得する
• フレンド一覧/助っ人一覧を表示するタイミングで取得
2019年の年末に向けて
• リリース後の効果
2019年の年末に向けて
• リリース後の効果
ログインフローの改善
• deck/getのさらなる改善
• モンスターの全件取得から差分取得に変更
• 前回取得時からの差分を取得
• 変更のあったモンスターのみの取得
• 差分取得にすることによりクライアントの処理も軽減
まとめ
• 起こっている現象をしっかりと分析
• ボトルネックとなっている箇所を修正
• 基本的な負荷対策や修正をしっかり行うことが大事
• 負荷対策の方法は色々ある
• Appサーバーの増強 / DBサーバーの増強、分散
• サーバーアプリケーションの改善
• クライアントの改善
特別なことは何もなく当たり前のことをしっかりと実行していく
まとめ
基本的なことを当たり前に実行できるチームが良いチーム
大規模トラフィックにどのように備えて負荷対策を実施しているのか?

大規模トラフィックにどのように備えて負荷対策を実施しているのか?

Editor's Notes

  • #13 CDNについて追加してもいいかも
  • #14 CDNについて追加してもいいかも
  • #58 ほぼ全て書き直す