elixirを使ったゲームサーバ
Hidetaka Kojo
XFLAG™スタジオ / mixi, Inc.
自己紹介
• 名前: 古城秀隆
• github: HidetakaKojo
• 所属: エックスフラグスタジオたんぽぽT
• お仕事:なんでも嫌がらずやります
昨今のスマフォゲームアプリ事情
• ゲームを複数人で楽しむというのは

当たり前になってきた
• 携帯でのよくあるマルチの構成
• turnserver, photon
• clientの一台がhostとなる

ようなserver-client構成
中継サーバ
Host Client
昨今のスマフォゲームアプリ事情
• 実況中継や大会など多くの人にプレイを視聴される
• e-sports
• モンストグランプリ
• 閉じられた世界から広くみられる世界に
要求されるもの
• 公平さを担保するために不正の排除
• ゲームセーブのようなapi処理だけでなく、ゲーム途中のロジッ
クもサーバ側に…
• サーバからリアルタイムにclientにpushするニーズはある
• メンテナンス直前にユーザにnotifyする
• イベント開始を通知する
• ゲームデータ更新等をユーザに促す
• サーバクライアントで双方向通信可能な構成
elixir & phoenix
• rubyのプロダクトが既にあるので、導入時の見た目的な
アレルギーが少ない(と信じたい)
• ゲームサーバなのでsimpleなapiサーバと常時接続型のコ
ネクションを簡単に利用したい
• 常時接続コネクションを維持しつつホットスワップで
deployを行いたい
• やっぱり流行には乗っておきたい
Architecture
• シンプルな構成例
phoenix
server
JSON API
WebSocket
MySQL
Redis
RabbitMQ
/ZeroMQ
LB
Architecture
• ユーザデータの取得やゲームセーブなどユーザドリブンで発生す
る処理はjson(msgpack) api
• websocketはsignup(json api)で発行されたtokenと

socket server listから返されるipを使って接続
• 実際に接続するサーバは一緒
• json apiはLBを挟みたいがwebsocketは挟みたくないため
• websocket接続先はサーバ側である程度コントロールできる
ようにしておきたいという希望もある
• アプリ起動時にサーバからのpush用の接続を作成
Architecture
• MySQLはもちろんPostgreSQLでもok
• adapter書いて好きなものを追加してもok
• ただしadapter書くならEcto2.0を待ってからのほうが
良さそう
• Ectoの設計上、shardingを書くのは比較的楽
• Ectoはphoenixで標準で疲れているDB wrapper
• 薄いRubyのActiveRecord相当のもの
Architecture
• redis
• よくあるキャッシュ用とdelayed_job用
• messaging queue
• pub/sub用
• phoenix channel(後述)の仕組みの一部で必要
Phoenix Channel
• phoenixが用意するover-httpなリアルタイム通信の仕組み
• L4の生のsocket通信ではない
• websocketのオーバヘッドは少なく、

内部のcowboyの実装にも特に問題はない
• 開発者曰く、40core/128gbのサーバで

2,000,000 clientは処理可能とのこと
• 性能向上の跡 http://goo.gl/w3BtRJ
Phoenix Channel
Phoenix Channel
• transport, channel, pub/sub という3つの要素で構成
• transport
• 常時接続コネクションを管理する足回り
• ユーザコネクションにつき1 (erlang) process
• コネクションとchannelとのやりとりを取り持つ
• 通常はシリアライズにjsonを用いるが、シリアライザを

書くことで比較的に簡単に変更できる
• msgpack, ProtocolBuffers, FlatBuffers
Phoenix Channel
• channel
• transportから送られてくるclientのmessageを受け取る
• topicという文字列で送信先を制御する
• channelにロジックを実装しmessageを処理する
• ここにゲームロジックを実装する!
• pub/subのpublisherとなってtopicのsubscriberの
transportにmessageを送信する
Phoenix Channel
• pub/sub
• デフォルトでerlangのpg2を使用している
• pg2でフロント分散するにはclusterを組み必要あり
• ただpg2はprocess group参加時に各nodeにlockが

発生するので別のMQを使用するほうが良さそう
• redis, RabbitMQ, ZeroMQなどに切り替え可能
ゲーム開始時の接続の流れ
• tokenを持ってwebsocketのリクエストを送信
• 認証が完了したらconnectionを確立
phoenix
server
connection
ゲーム開始時の接続の流れ
• json api等で受け取ったgame idをtopicに含めて

channelに接続
• games:fcfe5f21-8a08-4c9a-9f97-29d2fd6a27b9
• gameの参加者だった場合はchannel join成功
phoenix
server
join
event
ゲーム専用コネクションの有無
• アプリ起動時にサーバからのpush用のchannelに接続して
いると仮定するとゲーム開始時の通信は2通りの方法がある
• 起動時のwebsocketを使ってゲーム用のchannelを接続
• websocketを使い回すので無駄なheartbeat等を減ら
せる
• ゲーム開始時に別のゲーム用のwebsocketを接続
• 特定のサーバにゲーム用の接続を誘導できる
ゲーム状態の保持
• ゲームの実装方法もサーバ構成を左右する
• ゲームの状態をcacheに接続し、clientからchannelにmessageが来るたび
にcacheから状態を読み出し、演算、stateを保存する
• ターン制やレイテンシがそれほど気にならないゲーム向け
• websocketの接続先がどこでもよく、再接続にも強い
• ゲーム用のprocessを作成し、そこにゲームの状態を維持しつつmessage
を処理する
• 低レイテンシ要求があるMMOのmapのような分割された構成に向く
• 特定のサーバにゲーム参加者が接続をする必要があり、サーバ故障時な
どにゲームの状態が失われる可能性がある
client logic
• ゲームがオフラインでもプレイできる場合…
• client側にもロジックが必要
• 言語によって同じ実装でも結果が異なる場合がある
• c++やc#で書かれたロジックをサーバ側に持ってこれないかも検討している
• view層とゲームのコアロジックをいかに切り離すか
• phoenixがsocketを管理して、thriftを使ってc++やc#のロジックに演算処
理を委ねる
• そもそもこの実装が正しいアプローチなのかも含めて課題
• UnityNetworkの進化に期待したい気持ちも…
deploy
• xflagの既存のゲームではプルリクエストがmasterにmergeされたら
deployしていいというルールになっている
• exrmを使ったchannel接続を維持したままのホットスワップは現時点で
は問題なく実行できている
• アプリケーションのバージョンの管理が少し面倒
• ホットスワップの元々の想定はもっとdeploy頻度が低い環境なのかも?
• clientの挙動をコントロール可能なゲームなら再接続をきちんと行える
ような設計をしたほうがコストは低いかもしれない
• ここはもっといい方法がないのか模索しています
まとめ
• とりあえずまだまだ試行錯誤ではありますが、elixirでの要
求を満たすようなゲームサーバの実装は可能性がありそう
• 今後も継続して試験や導入事例の作成に取り組む予定
• elixir界隈の方、ぜひ情報共有をしましょう!
• http://www.slideshare.net/hidetakakojo/elixir-58090331

elixirを使ったゲームサーバ