オートマッチ/キューイングプレイヤー


8

Node.jsとRedisを使用しています。プレイヤーをオートマッチする信頼できる方法を考え出そうとしています。一致するサーバーがあり、複数のゲームサーバーがセットアップされています。

以下は私が起こらなければならないことです:

  1. プレーヤーはゲームの種類(小/中など)で参加リクエストを送信します
  2. マッチングサーバーは、プレーヤーを待っている現在のゲームタイプにプレーヤーを追加します
  3. ゲームサーバーはプレイヤーにゲームIDを送信します

現在、私はこれを次のように実装しています:

  1. マッチングサーバーはBRPOPを使用してgame:queue:smallをリッスンします
  2. game:queue:small:id = idが存在するかどうかを確認します
  3. game:id:usersの長さが<= 6(最大プレーヤー)かどうかを確認します
  4. プレーヤーをgame:id:usersリストに追加します
  5. ゲームの長さが6になったら、game:queue:small:idを削除します

一致するサーバーがgame:queue:small:idがないことを検出すると、次のようになります。

  1. INCRゲーム:nextGameId
  2. game:queue:small:idを以前に生成されたIDに設定します
  3. ゲームIDをgame:queue:waitingに追加します

ゲームサーバーは、BRPOPを使用して新しいゲームを待ちます。ユーザーが1人になると、ゲームのユーザーが2人以上になるまで待ってから、タイマーを開始します。それらがその時間内に満たされない場合、それらは持っているユーザーから始まり、その後game:queue:small:idを削除します(したがって、マッチメーカーに新しいゲームを要求するよう強制します)。

私の方法が機能している間、私はそれが生産でうまく機能すると確信していません、そしてそれは非常に入り組んでいるようです。次の問題の可能性を確認できます。

  • 待機リストからゲームIDを受け入れるとゲームサーバーがクラッシュし、ユーザーはgame:id:usersに追加されますが、何も起こりません(クラッシュ自体は問題ではありませんが、ユーザーがゲームキューに追加され続けると、 )
  • ユーザーが切断してゲームが開始されていない場合、ゲームサーバーはユーザーをgame:id:usersリストから削除します。それを行っている間、マッチメイキングサーバーはユーザーをリストに追加して、ゲームがいっぱいであると考え、キューから削除することができます。

私の最初の考えは、1つのゲームタイプを待っているユーザーの単一のキューに変更することでした。ただし、これにはさらに問題があります。

  • ユーザーが接続するサーバーがクラッシュした場合、ユーザーをキューから削除しないため、ユーザーが存在しない場合でも、そのユーザーはゲームに参加できます。ソートされたセットを使用してリクエストの時間を保存し、ゲームIDが返されるまでクライアントにポーリングさせることができますが、これは、そのクライアントがどれだけ待機したかわからないため、ゲームを開始するかどうかわからないことを意味しますユーザー数が少ない。
  • ユーザーをゲームに参加させないと、ユーザーが参加しているものを確認したり、待機しているユーザーとチャットしたりできません(ゲームIDが必要になるため)。

私がこれを設定した方法はどれも正しくないので、誰かがいくつかのより良い提案を提供できるかもしれないと思っていました。ゲームサーバーとマッチメイキングサーバーを別々にしておく必要がありますが、必要に応じて拡張するためです。


私はここで解決したデータベースの問題:stackoverflow.com/questions/15172556/...
クリス・エヴァンス

game:queue:small:id = idが存在するかどうかのチェック」では、IDをどのように取得しますか?
レーヨン

回答:


1

あなたの最初で一番のエラーは、ライブキューにデータベースを使用することです。そのデータは、マッチメイキングプロセスのプロセスメモリに保存する方がはるかに便利です。プロセスが互いに直接通信できるようにします。それから、プレイヤーがゲームに入れられたときに、キューからプレイヤーを削除することは、マッチメイキングサーバーの唯一の責任であるということも必要です。

マッチメイキングについてより一般的には、ゲームが始まるポイントまで正確に一致するかどうかの決定を遅らせます。4人のプレーヤーのゲームに適合する3人のプレーヤーがいる場合は、そのタイプのゲームをプレイする必要があると決定しないでください。また、4人目のプレーヤーの場合、そのプレーヤーが到着するまでに時間がかかる場合があり、その間に一部のプレーヤーが待機を終了する場合があります。これの適切な実装は、ゲームタイプごとにキューを用意し、各プレーヤーをリクエストに一致するすべてのキューに入れ、キューがいっぱいになったときにゲームを開始し、関係するプレーヤーをすべてのキューから削除します。


キューを適切に処理するためにRedisを使用していました。私は最初にサーバー自体でマッチメイキングを管理していましたが、それは非常にうまくいきましたが、このアプローチには2つの問題が見つかりました:スケールアウトする方法が見つからなかったこと、次にサーバーが別のサーバーで開始する新しいゲームをリクエストする方法です。それらすべてにメッセージを送信できますが、負荷は分散されませんか?
Chris Evans

1
@ChrisEvansスケーリングについてあまり心配する必要はありません。シンプルなマッチメイキングプロセスで、毎秒数千のゲーム開始を処理できます。うまくコーディングすれば、たとえ何百万もの顧客を獲得したとしても、マッチメイキングを複数のプロセスに拡張する必要はありません。ゲームサーバーの負荷を分散することに関しては、サーバーが一般に多数のゲームをそれぞれ処理できる場合、各ゲームサーバーが新しいゲームを順番に取得する単純なラウンドロビンアプローチが合理的に効果的です。それ以外の場合は、定期的にゲームサーバーにどれほど忙しいかを問い合わせることができます。新しいゲームごとに1回発生する必要はありません。
aaaaaaaaaaaa 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.