Автоматизация / организация очередей игроков


8

Я использую Node.js и Redis. Я пытаюсь придумать надежный способ автоматического сопоставления игроков. Существует соответствующий сервер, а затем несколько игровых серверов.

Вот что мне нужно, чтобы это произошло:

  1. Игрок отправляет запрос на присоединение с типом игры (маленький / средний и т. Д.)
  2. Соответствующий сервер добавляет игрока в текущий тип игры, который ожидает игроков
  3. Игровой сервер отправляет игроку идентификатор игры

В настоящее время я реализовал это следующим образом:

  1. Соответствующий сервер слушает игру: queue: small, используя BRPOP
  2. Проверяет, существует ли игра: queue: small: id = id
  3. Проверяет, есть ли игра: id: длина пользователя <= 6 (максимальное количество игроков)
  4. Добавляет игрока в игру: id: список пользователей, если он есть
  5. Если длина игры теперь равна 6, она удаляет игру: queue: small: id

Если соответствующий сервер находит игру: queue: small: id отсутствует, он делает следующее:

  1. Игра INCR: nextGameId
  2. Устанавливает game: queue: small: id для ранее созданного идентификатора
  3. Добавляет идентификатор игры в игру: очередь: ожидание

Игровые серверы ждут, используя BRPOP для новых игр. Когда они его получают, они ждут, пока в игре будет минимум 2 пользователя, затем запускают таймер. Если они не заполняются в это время, они начинают с пользователей, которые у них есть, и впоследствии удаляют game: queue: small: id (таким образом вынуждая сваха запрашивать новую игру).

Хотя мой метод работает, я не уверен, что он будет хорошо работать на производстве, и он кажется очень запутанным. Я вижу потенциал для следующих проблем:

  • Игровой сервер падает после принятия идентификатора игры из списка ожидания, в результате чего пользователи добавляются в игру: id: пользователи, но с ними ничего не происходит (сам сбой не является проблемой, но пользователи продолжают добавляться в эту очередь игр. )
  • Если пользователь отключается и игра не началась, игровой сервер удалит пользователя из игры: id: список пользователей. Пока он находится в процессе, сервер поиска совпадений может добавлять пользователя в список и думать, что игра заполнена, тем самым удаляя его из очереди.

Мои первые мысли состояли в том, чтобы перейти в единую очередь пользователей, ожидающих один тип игры. Тем не менее, это создает дополнительные проблемы:

  • Если сервер, к которому подключаются пользователи, дает сбой, он не удалит пользователя из очереди, оставляя этого пользователя в игре, когда он не существует. Я мог бы использовать отсортированные наборы для хранения времени запроса и проведения опроса клиента до тех пор, пока не будет возвращен идентификатор игры, но это будет означать, что я понятия не имею, сколько времени этот клиент ждал, и поэтому не знаю, стоит ли запускать игру. с меньшим количеством пользователей.
  • Не помещая пользователей в игру, они не могут ни видеть, к чему присоединились пользователи, ни общаться с ожидающими пользователями (так как для этого требуется идентификатор игры).

Ничто из того, как я это настроил, не кажется правильным, поэтому я надеялся, что кто-то сможет предложить несколько лучших предложений. Мне действительно нужно разделить игровые серверы и серверы сватовства, хотя бы для того, чтобы вырастить их по мере необходимости.


Проблема с базой данных, которую я решил здесь: stackoverflow.com/questions/15172556/…
Крис Эванс

В Проверяет, существует ли игра: queue: small: id = id , Как вы получаете идентификатор?
Район

Ответы:


1

Ваша первая и самая главная ошибка - использовать базу данных для оперативной очереди, поскольку эти данные намного лучше хранятся в памяти процесса в процессе установления соответствия. Пусть процессы общаются друг с другом напрямую. Кроме того, вы также в значительной степени обязаны, чтобы сервер сватовства отвечал за удаление игроков из очереди, когда они помещены в игру, как и должно быть.

В более общем плане, касательно организации матчей, откладывайте принятие решений о точных матчах до момента начала игры, если у вас есть 3 игрока, которые подходят для игры на 4 игроков, не решайте, что они должны играть в этот тип игры до того, как также четвертый игрок, это может занять много времени, и некоторые из них могут перестать ждать. Достойная реализация для этого состоит в том, чтобы иметь очередь для каждого типа игры и помещать каждого игрока во все очереди, соответствующие их запросу, затем, когда очередь заполнится, запустите игру и удалите вовлеченных игроков из всех их очередей.


Я использовал Redis как хорошо обрабатывает очереди. Первоначально я управлял установлением совпадений на самом сервере, и он работал очень хорошо, но я обнаружил две проблемы с этим подходом: я не смог найти способ его масштабирования и, во-вторых, как сервер запрашивает новую игру для запуска на другом сервере. Он может отправить сообщение всем им, но тогда нагрузка не будет сбалансирована?
Крис Эванс

1
@ChrisEvans Вы не должны слишком беспокоиться о масштабировании, простой процесс поиска совпадений может обрабатывать тысячи инициаций игры в секунду. Если только вы хорошо его закодируете, вам не понадобится поиск совпадений для масштабирования нескольких процессов, даже если у вас миллионы клиентов. Что касается балансировки нагрузки на игровые серверы, то простой круговой подход, при котором каждый игровой сервер по очереди получает новую игру, является достаточно эффективным, если серверы обычно способны обрабатывать большое количество игр каждый. В противном случае вы можете периодически спрашивать игровые серверы, насколько они заняты, это не должно происходить один раз за новую игру.
aaaaaaaaaaaa
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.