node.js возможна ли ситуация гонок в моём случае?

Всем привет. Я пытаюсь делать игровой сервер для небольшой браузерной онлайн игры. И вот я уперся в одну проблему.

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

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


Ответы (1 шт):

Автор решения: Алексей Якубин

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

Скажем, к вам пришёл новый игрок, сервер выпускает событие IPlayerCreated, по шине данных получатели, подписанные на это событие, получают его и запускают какую-то свою логику (скажем, сервис нотификаций показывает другим игрокам "К нам присоединилась <имя>").

Другой пример: при сборе игроков в лобби перед новой игрой все они подписываются на события IBulletLaunched, которые приходят от остальных игроков лобби. Уже во время игры, игрокам через шину данных будут постоянно прилетать эти события (скажем, с координатами снаряда) и обработчик будет решать попал ли он в нашего игрока или нет и сообщать клиенту.

Ключевые моменты здесь:

  1. Эти события и их обработка локальны для небольшой кучи игроков. На очередь сообщений (пусть это будет RabbitMQ) LobbyXXX подписаны только эти игроки, поэтому она не будет вынуждена обрабатывать космическое количество сообщений в секунду.
  2. Нет никакого одного потока с глобальным циклом, который бы ходил по всем игрокам и рассказывал им как жить. Вся обработка событий полностью асинхронна, изменения в игре происходят от обработчиков событий, а не некоего Потока на бекенде. Обработчики отвечают лишь за свой маленький участок (скажем снаряды) и легко горизонтально масштабируются, если у вас в игре вместо 10 снарядов в секунду стало 10000.

Событийная парадигма позволит вам приблизить ваше моделирование процессов к реальной жизни и отрисовывать на клиенте не только и не столько реакцию на нажатия игроком кнопочек, сколько изменения, которые эти нажатия (и не только они) вызвали.

→ Ссылка