★テーマ
大ヒットソーシャルアプリ「ドラゴンコレクション」の裏側 ~
超高トラフィックを支えるアプリ・インフラの“明日から使えるテクニック” 限定紹介!


●スピーカー
株式会社コナミデジタルエンタテインメント
ドラコレスタジオ マネージャー廣田 竜平氏

元々ギタフリ、ドラマニの開発をやっていた
現在ドラコレの技術責任者



●ドラコレがヒットした理由
 それまでクエスト、バトルが中心だったソーシャルゲームに
 カード収集の要素を取り入れる事によって、絶妙なモチベーションを生成



●超高トラフィック
 ドラコレの人気上昇に伴い、ピーク時はphpのページへのリクエストだけで
 *****req/secに達する。
 PVだけで言えば、国内の中規模クラスのサイトに匹敵する
 ***台のサーバで運用している
 (数値は桁数のみ公開、*****は5桁という意味)

 ○環境
  LAMP環境
  APC
  memcached
  ソフトウェアLB
  DNSラウンドロビン
  Zeus

  基本的にスケールアウト、スケールアップで対応している。



●よく「サーバはクラウドか?」という質問を受ける
サービス開始当初はパブリッククラウドを利用していた。
しかしトラフィックが増えると、問題が発生した。

 ○ディスクI/Oが不安定
  物理ディスクを占有できるサービスがなかった

 ○内部ネットワークのトラフィックの限界が分からない
  自分たちで管理しているわけではないので。
  トラフィックが大き過ぎたため、内部ネットワークをパンクさせてしまうこともあった。
  その際の原因の調査も、自分達で細かいところまで出来ないため、不便だった。

 ○クラウドサービス全体のメンテに都合を合わせる必要がある
  クラウドサービス全体のメンテをやられると、ゲーム側も当然サービスを止めることになる。
  それが月初だったりすると、課金への影響が大き過ぎる。

決してクラウドのパフォーマンスが悪いというわけではなく、不安定であることが問題。
パブリックあるゆえ、自分たちでは制御できない要因が多くある。
そのため、問題が出てもすぐには確認出来なかったりする。

一般的なPCのサイトでは特に問題にならないレベルだが、ユーザーの反応がすぐに出てくるモバイルのソーシャルゲームでは、致命的になる。

運用を開始してからかなり早い段階で、専用のシステムに移した。



●システムの引っ越し
 クラウドのサーバから、専用サーバへの移行。
 新しい環境にアプリとデータを移すという作業が必要。
 いかにメンテ時間を短くするかが課題だった。

 ○データ移行
  Webサーバは現行で使っているプログラムを置いておけばいいだけなので問題ない。
  DBのデータ移行が問題だった。
  その当時でデータ容量は数百GBになっていたため、データコピーにかなりの時間がかかる。
  
  そのため、新DBに対して、移行前から旧DBからレプリを取って同期するという方法を使った。
  手順としては下記の通り
  
  ①旧DBにSlaveを一台追加する(LBの振り分け対象には入れない)
  ②新DBのMasterに対して、①で追加したSlaveからレプリを取る
  ③新DBのMasterから、新DBのMasterにレプリされる

  こうすることによって、メンテ時はアクセスするDBの向き先を切り替えるだけで済むため、
  DBのデータ移行の作業が必要がなくなる。

  引っ越し後もしばらくは、トラブルで旧システムにことになる可能性もあるので、
  新DBから旧DBにレプリを行っていた。

  ネットワークの世界では関係ないことだが、新環境と旧環境で物理的に
  500kmほど離れていたため、実際に終わるまでは大きなプレッシャーがあった。
  結果的にメンテは数時間程度で終える事が出来た。



●5秒問題(モバイルソーシャルアプリ特有の問題)
 GREEでは、ユーザの端末からプラットフォームのガジェットサーバに行き、
 そこで認証してから各SAPのサーバに行く仕組みになっている。
 ガジェットサーバがSAPサーバからのレスポンスをずっと待っていると
 プロセスが待機状態になってしまうため、ガジェットサーバ側が5秒でタイムアウト設定している。
 そのため、SAPのサーバからGREEへのレスポンスを5秒以内に返さないとエラー扱いになり、
 それが一定回数までいくと公開停止されてしまう。

 高トラフィックになってくると、瞬間的なトラブルも許されなくなる。
 レスポンスに5秒以上かかりそうな場合には、
 PHPの処理を中断して「再度読み込んで下さい」というのメッセージを画面に出すようにしている。
 こうしてガジェットサーバへのレスポンスを早く返していれば、
 エラーは避けられる。

 実装方法としては、setitimer関数を使って、TIMER_PROF,ITIMER_REALを指定している。
 時間指定の単位を1秒未満の精度にする、タイムアウト時のHTTP変更を可能にする
 といった変更、追加もした。



●マイクロバースト問題
 トラフィックが増える中で、一部のレスポンスが極端に遅くなっていた
 遅延が発生するファイルに法則性が無かったが、全て9秒前後で処理が完了していた

 ○原因
  WEBサーバからDBサーバへのTCP接続で時間がかかっており、
  SYNパケをロストしている時に発生していた。

  SYNパケットを1回ロストすると3秒待機、2回目以降のロストは時間が倍々になっていく。
  例)1回目:3秒、2回目:6秒、3回目:12秒
  そのため、SYNパケットを2回ロストするとTCP接続に約9秒かかっていた。

  トラフィックのピーク時に、スイッチのキューで瞬間的に
  パケットが溢れている(マイクロバースト)ことが原因だった。
  定常的なトラフィックでは充分に余裕があったため、見逃していた。
  その当時はクラウドを使っていたため、なかなか原因を調べられなかった。

 ○RTOの変更
  アプリの全ての通信個所のタイムアウト、リトライを調整すれば、最適化できるかもしれないとなり、
  ネットワークに対するRTOを変更した

 初期RTOを1秒、再送のたび倍々とするのをやめ、常に1秒とした。
 オープンソースの改造やミドルウェアのパフォーマンスチューニングを行って対応した結果、
 半年間公開停止になることはなかった。



●いざという時の輪番アクセス
 システムの規模が大きくなると、新機能追加の負荷テストが難しくなる。
 本番環境と同じシステムがもう一つあれば理想だが、現実的には不可能。
 一般的にはスケールダウンした環境で負荷テストを行う。
 規模が大きくなると、テスト環境のn倍という単純計算では成り立たなくなる。

 ○判断基準
  新しいイベントをやる時は特に判断が難しくなる。
  過去の実績や各種パラメータから総合的に判断する。
  きつければシステム増強を行う。

 ○輪番アクセス
  不測の事態が発生した場合に、輪番アクセスを用意している
  user_idからいくつかのグループに分けて、定期的に利用出来る範囲を変えて行く方法。

  例)
   0時~1時:user_id1~100がアクセス可能
   1時~2時:user_id50~150がアクセス可能
   2時~3時:user_id100~200がアクセス可能

  これによって、サービスの開放率をコントロールできる
  (一部の人だけずっとアクセス出来ないという状態を避けられる)

 ゲーム全体のアクセスだけでなく、特定の機能などにこの仕組みを導入するケースもある
 システム上の何かがパンクした場合、ボトルネックとなっているパラメータのグラフをみながら、
 この開放率をコントロールしてピークが過ぎるのを凌ぐ。



●感想
 現在自分が携わっているソーシャルゲームの世界で最も大きいコンテンツの一つなので、
 話の内容的にも技術的にも自分に置き換えて捉える事が出来て、参考になる部分が多かった。
 データ移行の話は、自分がやることになった際には手法として選択肢の一つになるし、
 クラウドのデメリットという部分も今後自分でサービスを立ち上げる時の参考になる。

 また、5秒問題のルールは知らない部分だったので(自分が無知なだけかもしれないが)、
 具体的な対策も含めて聴けて良かったと思う。