負荷対策のため、エンジニアリングチームがやれることを全部やる
セッション冒頭では、モンストのアーキテクチャ構成についての説明がなされた。
下図のとおりモンストでは、ユーザーからのリクエストを受け付けるロードバランサーがあり、後段にアプリケーションサーバーが配置されている。データベースはmaster・backup構成。非同期処理にはRedis+batchが用いられている。
キャッシュ処理のためにMemcachedが多用されており、パケットをリレーするTurnサーバーによってマルチプレイが実現されている。監視システムとしては、Nagiosによるサーバー監視、Kibanaによるログ監視、CloudForecast、Grafanaによるモニタリングが行われている。
自社データセンターのサーバーと複数のクラウド事業者のサーバーを併用するハイブリッド構成になっていることも特徴である。通常時、本番環境の稼働サーバーは約1000台もの規模というから驚きだ。また、自社データセンターを冗長構成にすることで、高い可用性・耐障害性を実現している。
モンストのエンジニアリングチームはなぜ負荷対策を実施したのか。その理由を白川氏はこう語る。
「モンストでは、コラボイベントや限定クエスト、限定アイテムの配布などのタイミングでサーバーが高負荷になります。事前にユーザーへの告知をしているため、そのタイミングで多くの方がログインされるからです。
例年ですと、1年のうち、もっともアクセスが増えるタイミングは年末年始です。ちょうど新年を迎えたタイミングでアクセス量のピークを迎えます。なぜなら、0時から始まるガチャで強いキャラが出現することが、ユーザー間で認知されているからです」
過去2年間の年末年始では、モンストのエンジニアリングチームは苦い思いを味わってきた。2016年末では、サーバー高負荷によってデータベースのスロークエリが発生してしまい、緊急メンテナンスを実施。2017年末では、緊急メンテナンスは免れたものの、アプリにつながりにくい状態が2時間程度も続いてしまった。
「年末年始のタイミングで、ユーザーの方々にご迷惑をおかけしたくありません。これまでの反省を踏まえて、エンジニアリングチームでは2018年の年末に向けてやれることを全部やると決めました」
アプリ・インフラの両面からアプローチした負荷対策
エンジニアリングチームは大きく分けて2種類のアプローチを行った。1つはプログラムのロジックを見直すなどアプリケーション側を変えるアプローチ。そしてもう1つはサーバーやネットワーク回線を増強するなどインフラ側を変えるアプローチである。
まず白川氏は、アプリケーション側を変えるアプローチについて解説した。モンストでは、年末年始のタイミングで多くのユーザーがログインを行う。そのため、ログイン処理がアプリケーションのボトルネックになっていた。
その状況を改善するため「1.ログイン時に呼ばれる各処理の必要性の有無を精査し、処理数そのものを減らしていく」「2.ログイン時に呼ばれるAPIのうち、もっとも処理が重いものをリファクタリングする」といった軸で、負荷対策が進められていった。
モンストでは、ログイン処理のタイミングで「ゲームに必要なすべての情報」を取得することで、その後の画面遷移で通信を挟まずにユーザーにアプリを使ってもらえる設計にしていた。通常時はこの方法で問題ない。しかし、アクセスが増えるとログイン処理の負荷が高まってしまう欠点を抱えていた。
負荷対策として、この処理の改修が行われた。改修前は、アプリ起動からログインをしてホーム画面に遷移するまでのAPI呼び出し回数は合計13回。しかも、すべてのAPI呼び出しに成功しなければ、ユーザーはホーム画面までたどり着けなかった。
この課題を解決するため、エンジニアリングチームではAPI呼び出しの必要性の有無を精査。なんと13回から3回にまで削減できたという。これにより、アプリケーションサーバーの負荷が減るだけではなく、ネットワーク通信量の削減にも結びついた。
さらに、処理が重いAPIの高速化にも取り組んだ。このAPIは、ユーザーが所有しているすべてのキャラクター情報を取得するためのもの。ユーザーの所有キャラクターごとにアソシエーションに任せてデータを全件取得するため、仮に1ユーザーで最大5体のみ所持可能な情報であっても、機能によっては最大4200体で検索してしまうという課題があった。いわゆるN+1問題である。
この課題を解消するため、APIの処理フローを「事前にキャラクター情報を取得しておく」「ユーザーが所有するキャラクター情報の一覧を持っておく」「2つの情報を照らし合わせてつなぎ合わせる」流れに変更した。その結果、最大4200回発行していたクエリをわずか1回に削減できたという。
次に、インフラ側を変えるアプローチについて解説する。通常時、モンストのアプリケーションサーバーはCPUのコア数換算で13000coreが稼働している。また、DB性能限界へのアプローチとしてMemcachedによるキャッシュを多用している。そして、Memcachedはすべて自社のデータセンターのサーバーでまかなっているという。
システム構成の都合上、アプリケーションサーバーとMemcachedサーバー間の通信が頻発する。そのため、アプリケーションの可用性を担保するには、自社で持つデータセンターとアプリケーションサーバー間の物理的な距離が重要となる。クラウド事業者の選定をする場合にも、レイテンシーを非常に重要視しているそうだ。
年末年始の負荷対策のためアプリケーションサーバーの増強を行う際にも、この“レイテンシー重視”の方針が貫かれた。自社データセンターにあるMemcachedサーバーやデータベースサーバーとの物理的な距離がもっとも近いのは、言うまでもなく「自社データセンターにあるアプリケーションサーバー」である。そのため、このサーバー増強では自社データセンター内への相当数のサーバー配置が行われた。
また、クラウドサーバーの調達にもかなり注力した。各クラウド事業者との専用回線を結ぶことでネットワーク帯域を強化したほか、CPUコア数換算で26000coreものサーバーを確保したという。これは、これはサーバーの設定上のmax connectionの上限まで達するコア数である。
こうして、2018年末はどうなったか。結果としては、0時から15分程度は処理が重たくなったものの、2017年末の2時間と比較すると劇的な改善につながった。驚くべき推移である。
「エンジニアチームとして、まだまだやれることはたくさんあります。ユーザーのみなさまに快適なサービスを提供するため、これからも私たちの戦いは続いていきます」
お問い合わせ
株式会社ミクシィ