#amazon-web-services #aws-lambda #amazon-elastic-beanstalk
#amazon-веб-сервисы #aws-lambda #amazon-elastic-beanstalk
Вопрос:
Я работаю над простой онлайн-игрой, в которую будут играть стример и его зрители. Стример инициирует сеанс игры, создает игру, а затем предоставляет ссылку для подключения всем своим зрителям. Одна игровая сессия будет длиться ~ 10 минут.
Мой интерфейс — это SPA, который будет взаимодействовать с серверной частью с помощью REST API.
Я бы хотел развернуть его на AWS из-за их привлекательных возможностей вычислений по требованию и цен. Однако я хотел бы оптимизировать с минимальными затратами, сохраняя при этом параметры масштабируемости, используя мои предварительные знания об ожидаемом взаимодействии frontend-backend.
Предположения
- Иногда в игру могут играть 1000 (или даже больше) человек, в других случаях это может быть 0, с резкими колебаниями от минуты к минуте
- Серверная часть хранит состояние игры
- Стример и зрители чередуются по очереди
- Время принятия решения для зрителей ограничено (скажем, 10-15 секунд).
- В очередь зрителей каждый зритель может проголосовать за то, какие действия следует предпринять от имени зрителей
- интерфейс просмотра позволит пользователям повторно голосовать и обновлять свой голос
- интерфейс просмотра также будет периодически запрашивать у серверной части некоторую статистику о том, как голосуют все остальные зрители — предполагается, что эта статистика обновляется примерно раз в секунду, все сразу
- Каждый раз, когда стример или зрители заканчивают свой ход, состояние игры повторяется, и некоторый результат отображается на интерфейсе стримера
В течение одного игрового сеанса необходимо поддерживать следующее состояние:
- состояние игры — содержит текущее состояние игры.
- состояние голосования зрителей — содержит информацию о голосах всех зрителей.
- статистика голосов зрителей — содержит моментальный снимок статистики голосов зрителей.
Архитектура
Я пытаюсь выяснить, какой может быть оптимальная архитектура для такого приложения.
Первоначально я планировал иметь сервер с одним узлом и хранить состояние в памяти, но это не масштабируемо, а также может быть дорогостоящим, когда игра не воспроизводится. Если бы я попытался развернуть это на elastic beanstalk, я полагаю, что не было бы никакого способа гарантировать, что все игроки в игровой сессии всегда будут перенаправляться на один и тот же сервер.
Итак, из того, что я собрал, оптимальным способом может быть сохранение всего состояния в DynamoDB, реализация полного REST API с использованием лямбда-функций, а затем периодический вызов лямбда-функции (например, 1 раз в секунду), который обновит статистику голосования зрителей, а также обновит состояние игры, когда будет выполнен ход.принято (эта периодическая задача, вероятно, также может быть выполнена в одном экземпляре EC2, вы бы предпочли это вместо запланированного lambda?).
Итак, мои вопросы к вам::
- Есть ли в этом смысл?
- Не могли бы вы выбрать другую архитектуру, учитывая ограничения, которые я предоставил? Если да, то почему?
- Обмениваю ли я простоту разработки (написание отдельного веб-сервера в node против написания большого количества лямбд) на низкую стоимость развертывания?
Комментарии:
1. * Как долго вы хотите поддерживать состояние данных и статистические данные?
2. Только в течение одной игровой сессии ~ 10-15 минут
Ответ №1:
Сервер: Rest API могут быть созданы с использованием Api Gateway Lambda вместо сервера узла на ECS / ElasticBeanStack с учетом стоимости и масштаба. Даже если вы настраиваете простой сервер узлов в ECS, состояние хранения должно быть выгружено с сервера во внешнее хранилище данных, хотя с помощью фиксированных сеансов elastic load balancer вы можете пересылать запросы от одной игры / пользователя на тот же сервер.
Хранилище данных: для хранения состояния и статистики я вижу два варианта, учитывая, что долговременное хранилище не требуется.
- Redis: Пока число одновременных пользователей не слишком велико, мы можем масштабироваться с помощью автоматического масштабирования. Преимущества заключаются в низкой задержке, даже меньшей, чем у DynamoDB. Но масштабирование может стать проблемой, если общее количество пользователей колеблется от сверхнизкого до сверхвысокого за короткий промежуток времени без лишних затрат. Вот подробный пример.
- DynamoDB: это наверняка работает и легко масштабируется. Вам не нужно задание, которое выполняется каждые 1 секунду, вы можете легко включить динамические потоки с помощью Lambda для обновления статистики.
В большинстве случаев решением является комбинация DynamoDB и Redis.
Комментарии:
1. Я бы добавил, что вы можете использовать транзакции в DynamoDB для записи новых голосов и добавления их к записи с общим итогом или просто использовать вызов updateItem для увеличения счетчиков для записи с общим итогом. Если все сделано правильно, нет необходимости в том, чтобы лямбда-код прослушивал поток.
2. Еще один момент, на который следует обратить внимание: по умолчанию существует ограничение в 1000 параллельных лямбда-исполнений, OP должен знать об этом, но это мягкий предел, который может быть повышен.
3. @Maurice то есть вы потенциально могли бы позволить зрителям напрямую взаимодействовать с DynamoDB? Весь их вклад в DynamoDB — это их голосование, которое либо записывается, либо обновляется (если уже записано). Безопасно ли предоставлять доступ к DynamoDB непосредственно во внешнем интерфейсе? Можно ли было бы сделать что-то подобное с Redis? Но из ответа я предполагаю, что с точки зрения масштабирования было бы безопаснее использовать DynamoDB. Кроме того, похоже, что статистика голосования пользователей может быть распространена среди пользователей, использующих сервис pub / sub, потому что afaik это идеально соответствует его варианту использования.
4. Вы могли бы использовать API-шлюз для аутентификации авторизации и использовать его для прокси-вызовов API DynamoDB, если это достаточно гибко, зависит от ваших конкретных требований. Pub / Sub — это отдельное обсуждение / вопрос, но вы можете создать что-то подобное, используя другие сервисы AWS, например, на основе websocket с API Gateway.
5. Итак, у каждого пользователя приложения будет подключенная учетная запись twitch, их идентификатор twitch — это то, что будет их идентифицировать. Итак, у меня тогда был бы лямбда-код, который генерировал бы временный токен доступа, который будет использоваться интерфейсом для запросов DynamoDB (через API Gateway)? У меня пока нет большого опыта работы с аутентификацией, поэтому я немного смущен этим. Если pub / sub не подходит, для этого может быть достаточно периодического запроса DynamoDB из интерфейса для общей статистики. Учитывая, что API Gateway, похоже, способен регулировать запросы, этого может быть достаточно.