Отложенные фоновые события в онлайн игре?

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

Т.е. я генерирую событие, которое должно быть обработано в определенное время и результат обработки будет зависеть от актуальных на момент выполнения данных.



Как лучше обрабатывать такие события на сервере?



На ум приходит очевидное — добавлять событие в очередь с параметром «время», фоновый скрипт постоянно проверяет очередь и если есть события, которым пора выполняться, обрабатывает их все по очереди.



Беспокоит меня в таком подходе то, что при большом количестве участников, событий тоже может быть много, в том числе и назначенных на одно время. Их последовательная обработка может занять время и в час Ч, результата еще не будет (т.е игра отобразит что-то там, но не результаты, которых ждут игроки).



Возможно, есть какое-то более логичное решение для отложенных событий? или не стоит переживать по поводу скорости, а делать так, чтобы обработка занимала очень мало времени?
  • Вопрос задан
  • 3044 просмотра
Пригласить эксперта
Ответы на вопрос 7
akalend
@akalend
программирую
Беспокоит меня в таком подходе то, что при большом количестве участников, событий тоже может быть много, в том числе и назначенных на одно время. Их последовательная обработка может занять время и в час Ч, результата еще не будет (т.е игра отобразит что-то там, но не результаты, которых ждут игроки).

что мешает запустить не один а несколько процессов обработки очереди.
сделай монитор очередей и если очередь имеет маленькую пропускную способность (обработка элементов очереди за ед времени) то запускай дополнительный процесс и наоборот — убиваем лишние процессы при простое
Ответ написан
izmalk
@izmalk
А если серьезно — бой должен быть моментальным? Вот прибыло войско и бац — все полегли? Сделайте просто фриз настроек обороны в момент прихода врага и введите время боя — зависящее от количества войск или стандартное, например 15 минут реального времени. Т.е. у вас будет 15 минут чтобы посчитался результат схватки. Успел посчитаться — сохраняется и все равно ждем оставшееся время. Если же когда-нибудь столкнетесь с пределом производительности — просто продлевается время боя, в случае, если еще не посчитался результат.
Ответ написан
akalend
@akalend
программирую
Войско придет к соседу через час, без моего участия, состоится бой, результат которого будет зависеть от конфигурации войска соседа. При этом, сосед может поменять эту конфигурацию хоть в последнюю секунду.
кидаем событие: «войско пришло к соседу», время начало, конфигурация

разгребаем события, выбираем по времени -> время совпало:
«войско пришло к соседу»( конфигурация) -> инициация события: Бой( конфигурация 1, конфигурация 2, время )
Ответ написан
dmomen
@dmomen
А почему не попробовать таймер? Он инициируется когда возникает условия каких-то действий в определенный момент. В этот момент вызывается обработчик, действующие лица блокируются на время обработки, отработало — показали данные.

Вижу проблему только если серверов будет несколько и их будет почти невозможно синхронизировать.
Ответ написан
seriyPS
@seriyPS
Вопрос как-то странно задан, не понял что вам все-таки нужно… Чтобы все события гарантированно отрабатывали за заданное время? Или чтобы внутреннее состояние системы не нарушилось?

Я бы такого рода задачу решал с использованием менеджера очередей a-la RabbitMQ. Они поддерживают отложенное выполнение задач. Ну а данные о состоянии системы можно получать в момент старта задачи.
Проблема большого кол-ва юзеров решается классическим способом — увеличением кол-ва воркеров… Получать задачи от RabbitMQ могут несколько серверов-воркеров, так что параллелить можно в очень широких пределах.

Для вашего примера: записываете в очередь отложенное событие «напади на соседа». В час Ч эта задача запускается на каком-то из воркеров, берет из БД текущую конфигурацию войск противника и считает результат боя. После обсчета сохраняет в БД или информирует юзера или запускает другую задачу в очередь…
Ответ написан
vinxru
@vinxru
1) Помещаем в очередь все события.

До часа Х

2.1) Если время X не наступило, а процессор простаивает, рассчитываем исход битвы, но сохраняем результат во временную таблицу.
2.2) Если пользователь изменил условия, уничтожаем сохраненный результат во временной таблице.

Наступил час X

3.1) Если время X настало и во временной таблице есть рассчитанные данные, то копируем их в основное состояние игры.
3.2) Если время X настало и временная таблица пуста, то рассчитываем исход битвы.
Ответ написан
@Jazzist
Задание поступило — ушло в базу. Вне зависимости от авторизации игрока, персонажи выполняют задачу. Ходы можно инициализировать и просчитывать по крону.

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

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы