Top Banner
2016/04/20 株株株株株株株株 株株 株株 株株株株株株株株株株株株株株株株株株 - 株株株株株株株 -
34

ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

Jan 14, 2017

Download

Engineering

Suguru Shirai
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

2016/04/20株式会社グレンジ塚原 裕也

ポコロンダンジョンズとリアルタイム通信- サーバサイド編 -

Page 2: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

‣名前塚原 裕也‣所属株式会社グレンジ‣経歴 ・ 2008/04 SI のベンチャー企業に入社 ・ 2012/02 Cyber X 入社   - アイドルレボリューション   - メジャーリーグオールスターズ   - NBA2K オールスターズ   - サカつく S ワールドスターズ ・ 2014/11 グレンジへ異動   - ポコロンダンジョンズ 

自己紹介

Page 3: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

アジェンダ‣ポコダン概要‣利用技術‣サーバ構成‣データ‣機能‣発生した問題と対応

Page 4: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

ポコダン概要

Page 5: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

ポコダン概要‣リリースiOS : 2014 年 6 月Android : 2014 年 8 月‣最新バージョン3.6.1‣ダウンロード数500 万

Page 6: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

‣マルチプレイ導入2015 年 3 月開発期間は 8 ヶ月位当初は 2014 年内に導入予定だった‣チーム人数45 人弱サーバーサイド: 3.5 人クライアントサイド: 6.5 人

ポコダン概要

Page 7: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

•Nginx(1.4.4)•PHP(5.5.7)•Phalcon(1.2.6)•MariaDB(5.5.38)•Redis(2.8.4)•Memcached(1.4.15)

利用技術 - 非リアルタイム通信部分 -

Page 8: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

• Nginx(1.4.4)• Node.js(v0.10.32)• Socket.IO(0.9.17)クライアントのライブラリに合わせて 0.9.17 を選択。接続時にハンドシェイクが遅延した場合に一定期間ハンドシェイクを待つパッチを当てて利用している。

https://github.com/tico8/socket.io/tree/0.9.16-patched

• Redis(2.8.4)

利用技術 - リアルタイム通信部分 -

Page 9: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

‣ Socket.IO とは• Websocket 、 xhr-poling をサポートクライアントの環境次第で自動的に切り替え• Websocket 通信を数行で始められる• 接続確立は2段階方式

1.ハンドシェイク2.接続要求3.接続確立

利用技術 - リアルタイム通信部分 -

Page 10: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

‣ Redis の Pub/Sub とは• publish( 発行 ) 、 subscribe( 購読 ) の略• イベントが発行されると、購読者へ通知される

‣ マルチプレイでの利用場面• データ更新通知• プレイ情報の同期

利用技術 - リアルタイム通信部分 -

Page 11: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

・・・

ロードバランサ

・・・データ用pub/sub 用

ロードバランサwebsocket https

サーバ構成 - 全体 -

Page 12: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

• BIG-IP 製• SSL 対応• ラウンドロビン+ IP persistence 設定

- 同じ IP アドレスは、同じ node サーバへ- persistence のキャッシュ削除間隔を 1 秒程度- マスクは 255.255.255.255最近まで 255.0.0.0 になってて偏りが・・・

• sticky session を利用Socket.IO のコネクション確立通信( 2 発目)を同サーバに振るため

サーバ構成 - ロードバランサ -

Page 13: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

ロードバランサ②

同じ IP は同じサーバへ振れるが、 Socket.IO で問題が・・・

‣ persistenceありの場合サーバ構成 - ロードバランサ -

Page 14: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

‣ サブネットマスク• 255.0.0.0 の場合第1オクテットのみで振り分け

192.0.0.0 ~ 192.255.255.255 IP アドレス数 : 16777216→ 均等に割り振られない

• 255.255.255.255 の場合第4オクテットまで振り分けIP アドレス数 : 1→ 均等に割り振られる

サーバ構成 - ロードバランサ -

Page 15: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

ロードバランサ

‣ sticky sessionなしの場合

①handshake②connect

handshake と connect で違うサーバーへ振られてしまう可能性があり、コネクションが確立できない。( MemoryStore 利用時)

サーバ構成 - ロードバランサ -

Page 16: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

ロードバランサ①handshake②connect③connected

handshake と connect が同じサーバーへ振られるため、コネクションが確立できる。( MemoryStore 利用時)

‣ sticky sessionありの場合

サーバ構成 - ロードバランサ -

Page 17: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

‣ Nginx• 80 番ポートで受け• 3000 番ポートで Node.js に流し込む• リバースプロキシでサブドメインを割り当てた

Node.js に振る‣ Node.js

• 1 マスタープロセス、 1 ワーカプロセス※ワーカプロセスが Cluster 構成にできなかった• forever を利用しプロセス永続化

サーバ構成 -Web サーバ -

Page 18: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

server { listen 80; server_name localhost; index index.php index.html index.htm; set_real_ip_from 10.0.0.0/8; real_ip_header X-Forwarded-For; underscores_in_headers on;

location ^~ /pocolon_dungeons_node/ { proxy_pass http://127.0.0.1:3000/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } location ^~ /pocolon_dungeons_node/socket.io/ { … }}

/etc/nginx/conf.d/pocolon_dungeons_node.confサーバ構成 -Web サーバ -

Page 19: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

• pub/sub 用とデータ用の 2 種類• pub/sub 用はルーム単位で振り分け• データ用は PHP 側からも利用する

サーバ構成 -Redis サーバ -

Page 20: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

データ -Redis のキー -1.マッチング検索用 ( ソート済みセット型 )位置情報、ルーム ID を登録2.ルーム情報用 ( ハッシュ型 )ルーム詳細情報を登録・ダンジョン情報・ステータス管理 ( マッチング中、クエスト中 )・位置情報・アプリバージョン3.メンバー情報用 ( ハッシュ型 )デッキ情報 ( 装備 / モンスター ) などを登録

Page 21: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

4.ロック用 ( 文字列型 )ルーム情報、メンバー情報のキーを更新する際のロックに利用。SETNX()+EXPIRESETNX=“SET if Not eXists”

キーが存在したらセット出来ないのを利用し、キーのセットと削除でロックを実現。

データ -Redis のキー -

Page 22: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

機能 -処理の流れ -• ルーム作成 /参加

PHP⇒Node.js の一連の処理が完了して、 Websocket のコネクションが確立出来たら処理完了。• クエスト開始

PHP 側で DB に登録後、 Node.js で待ち合わせ処理をし、マルチプレイ開始。• クエスト中基本的に Websocket 通信だが、 DB操作が必要な場面は PHP 側で処理される。 ( コンティニュー等 )• クエスト終了

Websocket のコネクション破棄後、 PHP 側で DB 更新が行われる。

Page 23: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

•マルチプレイ以外の機能全て•ルーム作成、参加※ websocket のコネクション確立部分はNode.js

•ルーム検索•その他(シングルプレイ共通部分)プレイヤー情報取得、ドロップ抽選、ログなど DB操作が絡む処理•Redis のデータは Node.js 側と共有

機能 - 非リアルタイム通信部分 -

Page 24: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

機能 - リアルタイム通信部分 -•クエスト開始後のほぼ全ての処理コンティニューなど DB操作をする際は PHP の通信も行っている•コネクション確立、破棄コネクション時のユニーク ID を Redis に登録している•クライアントから送られたデータを受け流すゲームロジックは持たない。•同期フロア待ち合わせ、盤面復旧。•ソケット切断一定時間応答のないプレイヤーを切断。•ソケット再接続

Page 25: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

‣PHP 側•位置情報、合言葉などを受け取り•Redis データ登録マッチング検索用、メンバー情報用などキーを複数に分けている。•デッキ情報など表示に使うデータを返す

‣Node.js 側•ユーザ ID 、ルーム ID などを受け取り•Redis データ更新ルーム情報のステータスをマッチング中に。ソケット接続完了ステータスに。•デッキ情報など表示に使うデータを通知

機能 - ルーム作成 -

Page 26: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

‣PHP 側•位置情報、合言葉などを受け取り•Redis データ取得•絞り込み条件-同一アプリバージョン機能やバグに差異が生じ、盤面がズレる原因になるため。-位置情報が近いルーム上限数になるまで、徐々に距離を延ばして検索を繰り返す(距離の上限もある)

•ルームのリスト及び表示用データを返す

機能 - ルーム検索 -

Page 27: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

‣ PHP 側• ルーム ID などを受け取り• Redis データ更新メンバー情報に自身を追加※ソケット未接続ステータス• ルーム内のユーザのデッキ情報など表示用データを返す

‣ Node.js 側• ユーザ ID 、ルーム ID などを受け取り• Redis データ更新ソケット接続済みステータスに更新• 更新情報など表示に使うデータを全メンバーへ通知

機能 - ルーム参加 -

Page 28: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

機能 - 同期 / 待ち合わせ -‣ Node.js 側

1.各端末から準備完了イベントを発行2.自身の状態を準備完了ステータスに更新3.一定時間応答のないユーザーの切断処理4.全員が揃うまでは待機を全メンバーへ通知5.全員が揃ったら同期完了を全メンバーへ通知

Page 29: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

機能 - ソケット切断 -‣ Node.js 側

• 生存確認イベントが一定時間来ないプレイヤーのソケットを切断• Redis データ更新

- ホストが離脱した場合は解散 or権限委譲- ゲストの場合、ホストに権限委譲

• 切断情報を全メンバーに通知

Page 30: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

‣ Node.js 側一定時間内の再接続要求は再度ルームに紐付けし直す。• ユーザ ID 、ルーム ID などを受け取り• Redis データ更新自身のコネクション ID を書き換える• 更新情報など表示に使うデータ全メンバーへ通知

機能 - ソケット再接続 -

Page 31: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

機能 -その他イベント -•生存確認•なぞり•クエスト開始通知•プレイヤーターン終了•コンティニュー•リタイヤ•スキル使用•コミュニケーション

Page 32: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

‣プロセスを Cluster 構成にできない【原因】Redis周りの独自実装が原因。MemoryStore を利用してセッション管理をしていたため、別のプロセスに振られると処理できない。【一次対応】1 サーバにつき 1 マスタープロセス、 1 ワーカプロセスにした。➡ 1 コアだったため、別プロセスの影響を受け、 Node の処理が詰まることがあった【恒久対応】素直に RedisStore を利用すれば別のサーバ / プロセスに振られても問題なくセッション維持ができる。(今週リリースします)

発生した問題と対応

Page 33: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

LB①handshake③connect④connected

handshake と connect が別サーバーへ振られても、コネクションが確立できる。つまり sticky session も不要になる。

‣ RedisStoreを利用した場合 ②セッション共有

④セッション情報取得

発生した問題と対応

Page 34: ポコロンダンジョンズとリアルタイム通信 -サーバサイド編-

ご静聴ありがとうございました。