Я использую Node.js и Redis. Я пытаюсь придумать надежный способ автоматического сопоставления игроков. Существует соответствующий сервер, а затем несколько игровых серверов.
Вот что мне нужно, чтобы это произошло:
- Игрок отправляет запрос на присоединение с типом игры (маленький / средний и т. Д.)
- Соответствующий сервер добавляет игрока в текущий тип игры, который ожидает игроков
- Игровой сервер отправляет игроку идентификатор игры
В настоящее время я реализовал это следующим образом:
- Соответствующий сервер слушает игру: queue: small, используя BRPOP
- Проверяет, существует ли игра: queue: small: id = id
- Проверяет, есть ли игра: id: длина пользователя <= 6 (максимальное количество игроков)
- Добавляет игрока в игру: id: список пользователей, если он есть
- Если длина игры теперь равна 6, она удаляет игру: queue: small: id
Если соответствующий сервер находит игру: queue: small: id отсутствует, он делает следующее:
- Игра INCR: nextGameId
- Устанавливает game: queue: small: id для ранее созданного идентификатора
- Добавляет идентификатор игры в игру: очередь: ожидание
Игровые серверы ждут, используя BRPOP для новых игр. Когда они его получают, они ждут, пока в игре будет минимум 2 пользователя, затем запускают таймер. Если они не заполняются в это время, они начинают с пользователей, которые у них есть, и впоследствии удаляют game: queue: small: id (таким образом вынуждая сваха запрашивать новую игру).
Хотя мой метод работает, я не уверен, что он будет хорошо работать на производстве, и он кажется очень запутанным. Я вижу потенциал для следующих проблем:
- Игровой сервер падает после принятия идентификатора игры из списка ожидания, в результате чего пользователи добавляются в игру: id: пользователи, но с ними ничего не происходит (сам сбой не является проблемой, но пользователи продолжают добавляться в эту очередь игр. )
- Если пользователь отключается и игра не началась, игровой сервер удалит пользователя из игры: id: список пользователей. Пока он находится в процессе, сервер поиска совпадений может добавлять пользователя в список и думать, что игра заполнена, тем самым удаляя его из очереди.
Мои первые мысли состояли в том, чтобы перейти в единую очередь пользователей, ожидающих один тип игры. Тем не менее, это создает дополнительные проблемы:
- Если сервер, к которому подключаются пользователи, дает сбой, он не удалит пользователя из очереди, оставляя этого пользователя в игре, когда он не существует. Я мог бы использовать отсортированные наборы для хранения времени запроса и проведения опроса клиента до тех пор, пока не будет возвращен идентификатор игры, но это будет означать, что я понятия не имею, сколько времени этот клиент ждал, и поэтому не знаю, стоит ли запускать игру. с меньшим количеством пользователей.
- Не помещая пользователей в игру, они не могут ни видеть, к чему присоединились пользователи, ни общаться с ожидающими пользователями (так как для этого требуется идентификатор игры).
Ничто из того, как я это настроил, не кажется правильным, поэтому я надеялся, что кто-то сможет предложить несколько лучших предложений. Мне действительно нужно разделить игровые серверы и серверы сватовства, хотя бы для того, чтобы вырастить их по мере необходимости.
источник
Ответы:
Ваша первая и самая главная ошибка - использовать базу данных для оперативной очереди, поскольку эти данные намного лучше хранятся в памяти процесса в процессе установления соответствия. Пусть процессы общаются друг с другом напрямую. Кроме того, вы также в значительной степени обязаны, чтобы сервер сватовства отвечал за удаление игроков из очереди, когда они помещены в игру, как и должно быть.
В более общем плане, касательно организации матчей, откладывайте принятие решений о точных матчах до момента начала игры, если у вас есть 3 игрока, которые подходят для игры на 4 игроков, не решайте, что они должны играть в этот тип игры до того, как также четвертый игрок, это может занять много времени, и некоторые из них могут перестать ждать. Достойная реализация для этого состоит в том, чтобы иметь очередь для каждого типа игры и помещать каждого игрока во все очереди, соответствующие их запросу, затем, когда очередь заполнится, запустите игру и удалите вовлеченных игроков из всех их очередей.
источник