Практический пример архитектуры на основе CQRS в ответах на игры PK

база данных Архитектура игра WebSocket
1. Введение

Проектирование на основе предметной области (DDD) стало горячей темой в эпоху микросервисов.В области DDD мы часто видим архитектуру с разделением ответственности за выполнение команд и запросов (CQRS). Поскольку сама архитектура CQRS — это только идея разделения чтения-записи, существуют различные способы реализации. Например, хранилище данных не разделено, это только разделение чтения-записи на уровне кода, что также является воплощением CQRS, затем хранилище данных отделено от чтения и записи.Командная сторона отвечает за хранение данных, сторона запроса отвечает за запрос данных, а сторона запроса отвечает за запрос данных. Данные на терминале синхронизируются через событие, генерируемое командным терминалом, который также является реализацией архитектуры CQRS. Эта статья знакомит с практикой последней реализации архитектуры CQRS при разработке системы PK, отвечающей в режиме реального времени. Кроме того, мы также представим режим Event Sourcing. В этой статье считается, что архитектуру CQRS можно лучше использовать в сочетании с режимом Event Sourcing.

2. Практические сценарии

В начале 2018 года стали популярны такие продукты, как ответы на вопросы и бросание монет, и эти продукты стали популярными порталами трафика. Ниже приведены несколько продуктов PK с ответами на рынке: Mind King, Public Comment Answer PK, Strongest Answer.

Геймплей PK в режиме реального времени в основном таков: случайным образом сопоставьте противника в определенной области или начните игру в игре, пять вопросов за игру, без реквизита, ответ 200 очков, чем больше Чем меньше медленных очков, тем неправильный ответ нет. Каждый вопрос находится на верхнем пределе времени в течение десяти секунд.Если вы отвечаете правильно в первую секунду, вы должны использовать вторую (т.е. 9 секунд), у вас есть 180 баллов, у вас осталось 160 баллов, поэтому вы можно нажать Последний вопрос дублируется. В итоге оценка судей по мнению обеих сторон.

В процессе PK будет много данных о боевой ситуации обеих сторон, таких как: счет каждого раунда, количество последовательных правильных ответов (обычно называемых комбо в игре), самые последовательные правильные ответы в игра, количество последовательных побед и т. д.

3. Конструкция системы 3.1 Способ связи

Чтобы построить систему ответа на вызовы PK в реальном времени, нам сначала нужно выбрать метод связи между интерфейсом и сервером.

3.1.1 HTTP-опрос

Протокол http — это протокол, используемый на уровне приложений. Он основан на протоколе tcp. Протокол http также должен иметь трехстороннее рукопожатие для отправки информации при установлении соединения. HTTP-соединение делится на короткое соединение, длинное соединение, короткое соединение заключается в том, что для каждого запроса требуется три рукопожатия для отправки собственной информации, то есть каждый запрос соответствует ответу. Длительное соединение предназначено для предотвращения разрыва TCP-соединения в течение определенного периода времени.

Клиент связывается с сервером, клиент должен инициировать, а сервер возвращает результат. Клиент активен, а сервер пассивен. Поэтому основными недостатками этого метода являются: относительно высокие коммуникационные ресурсы и плохая своевременность информационного потока.

3.1.2 веб-сокет еще длиннее

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

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

Однако, чтобы быть совместимым с различными средами мобильных устройств и повысить доступность системы, сервер обычно должен поддерживать два внешних и внутренних метода связи, HTTP-опрос и длинное соединение через веб-сокет. Система обычно предпочитает использовать веб-сокет для установления длинного соединения между внешним и задним концами.Если внешний интерфейс не может поддерживать веб-сокет и происходит сбой установки, он будет использовать HTTP-опрос для связи.

3.2 Протокол связи

После подтверждения того, что поддерживаются два метода связи, http и websocket, нам нужно согласовать два протокола связи.

3.2.1 http

При использовании http-связи в основном необходимо согласовать API, предоставляемый сервером. Как показано на рисунке ниже, этапы использования http-связи между интерфейсом и сервером:

1) сообщить о соответствующем запросе;

2) опрос для получения совпадающих результатов;

3) После получения информации об успешном сопоставлении сообщить о готовности;

4) Опрос для получения информации, связанной с игрой (информация о хосте и целевом игроке и т. д.);

5) Получить следующий раунд вопросов, если вопросов нет, перейти к шагу 7;

6) Сообщите ответ игрока на вопрос раунда и получите результат раунда. Опрос до конца раунда, переход к шагу 5;

7) Получить информацию о результате игры, и игра окончена.

3.2.2 websocket

Как показано на рисунке ниже, при обмене данными на основе длинного соединения через веб-сокет этапы обмена данными в начале и в конце следующие:

1) Клиент сообщает об ожидающем запросе игрока на сопряжение;

2) Сервер отправляет сообщение об успешном сопряжении;

3) Клиент отправляет обратно сообщение о готовности начать игру;

4) Сервер отправляет актуальную информацию об игре и вопросы первого раунда;

5) Клиент сообщает ответ игрока;

6) Сервер подталкивает результат ответа раунда;

7) Если раунд заканчивается (оба игрока завершили ответы), сервер подтолкнет результаты раунда и вопросы следующего раунда и перейдет к шагу 5. Если все раунды закончились, переходим к шагу 8;

8) Сервер подталкивает результат игры, и игра заканчивается.

4 Почему стоит выбрать CQRS и Event Sourcing 4.1 CQRS против CRUD

В большинстве случаев мы можем представить информационную систему как хранилище данных, которое можно добавлять, удалять, изменять и проверять.Все функции системы могут быть преобразованы в создание, просмотр, обновление и удаление на объектной модели объекта. структура хранения (CRUD). И когда требования становятся сложными, шаблон CRUD показывает свою неадекватность. Мы можем захотеть просмотреть записи особым образом: например, объединить несколько записей в одну или объединить записи из разных мест в одну виртуальную запись. Однако в реальной работе есть много ограничений: обычно мы можем объединять только определенные данные, а иногда хранимая информация совсем не соответствует предоставленной нами информации. Таким образом, бизнес-архитектура разделения чтения-записи является лучшим выбором для устранения несогласованности модели чтения-записи.

CQRS (Command Query Responsibility Segregation, то есть Command Query Responsibility Segregation) был впервые предложен Грегом Янгом. По сути, это механизм разделения чтения-записи. Схема его архитектуры выглядит следующим образом:

Разделение команд и запросов позволяет нам лучше разбираться в деталях объектов и лучше понимать, какие операции изменяют состояние системы. Таким образом, система имеет лучшую масштабируемость и повышает доступность системы. Архитектурная идея CQRS может быть реализована несколькими способами:

  1. Наиболее распространенной архитектурой CQRS является разделение базы данных на чтение и запись;

  2. Базовое хранилище системы не отделено, но отделен логический код верхнего уровня;

  3. Базовое хранилище системы разделено: на стороне команд используется технология Event Sourcing для хранения событий в хранилище событий, а на стороне запросов сохраняется последнее состояние объекта для обеспечения поддержки запросов.

Применимые сценарии архитектуры CQRS:

  1. Когда модель записи и модель чтения приложения сильно различаются;

  2. Когда производительность запросов и производительность записи системы необходимо оптимизировать отдельно, особенно для систем с очень высоким соотношением чтения/записи, необходимо разделить чтение и запись;

  3. Когда системе необходимо одновременно обеспечивать высокую скорость одновременной записи и чтения, поскольку система, основанная на архитектуре CQRS, может максимизировать скорость записи на стороне команд, легко обеспечить масштабируемую модель чтения на стороне запросов.

  4. При использовании DDD, потому что архитектура CQRS позволяет нам реализовать модель предметной области, свободную от дисбаланса импеданса объектов и баз данных, который привносит любая структура ORM.

4.2 Event Sourcing

Основная особенность Event Sourcing (ES) заключается в том, что он не сохраняет последнее состояние объекта, а сохраняет все события, сгенерированные объектом, и получает самое последнее состояние объекта посредством обратного отслеживания событий. Обычно мы сохраняем самое последнее состояние объекта в базе данных каждый раз, когда объект участвует в бизнес-действии, то есть данные в нашей базе данных отражают текущее последнее состояние объекта.

Напротив, трассировка источника событий не сохраняет последнее состояние объекта, а сохраняет каждое событие, произошедшее с объектом.Все события, сгенерированные объектом, будут храниться в базе данных в хронологическом порядке. Когда нам нужно последнее состояние объекта, нам нужно только сначала создать пустой объект, а затем воспроизвести все события, связанные с объектом, в порядке возникновения от первого до последнего.Этот процесс представляет собой откат событий.

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

Однако при практике ЭС возникает большая проблема с хранением и запросом — так как все релевантные события, влияющие на состояние объекта, записываются, получение последнего состояния объекта требует повторного воспроизведения событий, а время, необходимое для этого процесса, равно пропорционально количеству событий, когда количество данных увеличивается, время получения последнего состояния объекта также будет увеличиваться. Кроме того, во многих операциях бизнес-логики обычно требуется «чтение» для проверки перед «записью», поэтому системы, использующие архитектуру ES, обычно кэшируют копию последнего состояния объекта и выполняют «прогрев» при запуске. , чтобы прочитать все связанные события объекта для возврата.

Таким образом, при чтении объектов, т. е. при загрузке последнего состояния агрегированного корневого объекта, производительность запросов не влияет на доступность системы. Сценарии, требующие «чтения» перед «записью», неизбежно столкнутся с проблемами параллелизма, поэтому операция отслеживания событий с возвратом должна быть атомарной. На практике ES часто используется в сочетании с очередями сообщений для обеспечения ACID (атомарность, непротиворечивость, изоляция, долговечность) моментальных снимков отслеживания событий.

4.3 Анализ применимости

Применимость архитектуры CQRS и Event Sourcing в системе PK, отвечающей в режиме реального времени:

1. Чтение и запись модели  

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

Более того, для поддержки двух коммуникационных протоколов http и websocket разделение чтения и записи стало более масштабируемым и удобным в сопровождении.

2. Соотношение чтения и записи  

Основываясь на протоколе http-опроса, соотношение чтения и записи в системе PK, отвечающей в реальном времени, относительно высокое, потому что в игре с пятью раундами записывается максимум 10 событий, и клиенту необходимо опросить соответствующие игровые данные. .

3. Масштабируемость на стороне запроса  

Система PK, отвечающая в режиме реального времени, должна иметь хорошую масштабируемость на стороне запросов. Режим взаимодействия с игрой постоянно меняется, и сторона запроса должна расширять различные возможности запроса данных, такие как: количество последовательных побед, количество последовательных выигрышных раундов, наличие знаний (последний раунд превосходит счет) и повтор процесса ответа (приглашение друзей и собственные ответы) запись ПК), статистика игры игрока и т.д. Таким образом, разделяя чтение и запись и используя Event Sourcing, наша система может более удобно предоставлять легко масштабируемую модель чтения.

5. Архитектурная практика 5.1 Модель предметной области

Основываясь на архитектуре микросервиса и дизайне DDD, мы разделяем фоновый домен на: контекст PK, контекст сопоставления, контекст NPC, контекст учетной записи игрока и контекст банка вопросов. Основным контекстом фоновой системы ответа ПК в режиме реального времени является контекст ПК. Эта статья в основном знакомит с дизайном и практикой контекста ПК. На следующем рисунке показано моделирование контекста ПК:

В контексте PK мы управляем процессом PK посредством агрегирования Game.Как показано на рисунке выше, Game включает в себя несколько (обычно 5 раундов в игре) раундов (Round), а основным атрибутом раунда является question (Вопрос). ), а раунд содержит две сущности Player Round (PlayRound).

В поле Game запись PK игрока представляет собой информацию о результате игры, которая представляет собой учетные данные и заглушку для очистки активов игрока.

5.1 Инициализация игры — протокол двухэтапной фиксации

Чтобы повысить фактическую вероятность успешного сопоставления PK (многие игроки входят в процесс сопоставления, а затем выходят) и улучшить игровой процесс, мы можем извлечь уроки из двухэтапного протокола фиксации при построении протокола сопоставления для ответа PK 1 на 1. : два После того, как игрок сообщает об ожидающем запросе на сопоставление, контекст сопоставления асинхронно формирует пару из двух игроков.В это время сервер домена PK и два игрока не знают, готовы ли друг к другу к матчу.Чтобы обеспечить функцию ACID этого раунда сопоставления. Серверу необходимо разделить процесс сопоставления на фазу подготовки и фазу отправки.

Как показано на рисунке ниже: После того, как игрок A сообщает о запросе на сопоставление, сервер сопоставляет игрока A с игроком B из той же зоны соревнований и того же ранга на основе стратегии сопоставления. В этот момент сервер отправляет уведомления о подготовке игроку А и игроку Б соответственно, затем ждет, пока и игрок А, и игрок Б подтвердят совпадение, и фиксирует совпадение на сервере. После подтверждения обоих игроков игра официально начинается. Если некоторые игроки не подтверждают эту подготовку после тайм-аута (клиент не получает событие начала игры, отправленное сервером в течение согласованного периода тайм-аута), соединение считается недействительным, и клиент перезапускает процесс сопоставления и повторно сообщает об ожидающем сопоставлении. request , пока сопряжение не будет успешным.

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

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

5.2 Основной процесс игры — CQRS

При обработке объектов игрового домена мы разделяем запросы на чтение и запись доменных служб на основе CQRS. Если взять в качестве примера процесс ответа игрока, как показано на рисунке ниже, основной процесс таков:

1) Клиент сообщает ответ игрока и контекстную информацию;

2) анализировать командный процессор для обработки выделенной части информации, игрок отвечает на команду запроса, и эта команда относится к процессу полимеризации игры;

3) Игровой агрегат преобразует ответ игрока на событие ответа (в основном, включая GameID, PlayerID, Roundindex, Raundime, счет и т. Д.), Возвращая оценку текущего раунда игрока и сохраняет событие;

4) После сохранения допустимого игрового события в очередь сообщений будет отправлено сообщение о добавлении события (чтобы предотвратить конкуренцию общих данных, сообщение здесь хэшируется в соответствующий раздел в шине сообщений в соответствии с консистенцией gameId hash), Обрабатывается подписчиками обработчика просмотра игры;

5) Процессор просмотра игры отслеживает события соответствующей игры в соответствии с отслеживаемыми событиями и генерирует последние данные просмотра игры, включая ход игры и статус игры каждого персонажа-игрока (текущий счет, количество комбинаций, текущая самая длинная пара и др.);

6) сохранить последнее сгенерированное представление в базе данных представлений, чтобы обработчик запросов предоставил API для использования;

7) Процессор просмотра игры отправляет последнюю информацию о ходе игры в очередь сообщений и отправляет ее клиенту на основе соединения через веб-сокет или другие службы домена для обработки (например, после завершения игры службе домена учетной записи требуется урегулировать игру для каждого игрока игрового актива);

8) На основе клиента подключения к веб-сокету сервер будет активно передавать информацию о ходе игры, включая текущий раунд, название следующего раунда, результат первого раунда и другие данные;

9) На основе клиента связи с опросом HTTP клиент запрашивает соответствующую информацию о состоянии игры через API опроса.

5.3 Просмотр игры — Источник событий

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

В ответе PK данные, которые необходимо отображать на стойке регистрации, включают, помимо прочего:

1) Текущий счет раунда

2) Общий счет текущей игры

3) комбо текущего раунда

4) Игровые данные соперника

5) Будь лор (последний раунд нагоняет счет)

6) Самое длинное последовательное количество правильных ответов в раунде

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

5.4 Другое 5.4.1 Конечная согласованность

При использовании архитектуры CQRS, поскольку между чтением и записью будут задержки, это означает, что модель согласованности системы — Eventual Consistency. В ответной игре PK в непротиворечивости и доступности данных мы отдаем приоритет обеспечению доступности сервисов, и допустимо обеспечить окончательную непротиворечивость данных (задержка TP999 контролируется в пределах 200 мс).

Чтобы гарантировать окончательную согласованность, нам нужно сделать:

A. MQ гарантирует, что сообщения не будут потеряны;

B. Любой потребительский поток должен убедиться, что он полностью обработан перед отправкой ACK в MQ;

C. Каждый поток-потребитель является идемпотентным для любой обработки сообщений;

5.4.2 Идемпотент запроса команды

После того, как командный запрос отправлен, по разным причинам запрашивающая сторона не может получить правильный ответ, в то время как запрошенная сторона выполнила операцию правильно. Если запрос будет повторно отправлен в это время, это приведет к повторным операциям. В архитектуре CQRS/ES одна и та же команда идентифицируется путем объединения идентификатора корневого объекта, номера версии и CommandId, а запрос команды обрабатывается идемпотентно. На практике мы в основном выполняем идемпотентную проверку с помощью ограничения уникального ключа базы данных.

5.4.3 Параллельная обработка

Обработка одновременной обработки в основном связана с необходимостью чтения для записи бизнес-сценариев, таких как обработка данных PK, связанные с ними данных (PK Players отвечает данным). Чтобы справиться с профилактикой одновременного событий, принес задачу согласованности данных, CQRS / ES в случае первого приема впервые обслуживается строго насильственным корнем полимеризации состояния, изменился одним потоком атомной эксплуатации. Система PK в реальном времени ответа, способная поддерживать широкомасштабный поток, обязательно в распределенной среде, поэтому мы можем производить с помощью мероприятий, связанных с сущностями к тому же разделу через очередь сообщений (например, кафка), то же самое разбиение, чтобы Обеспечить упорядоченную обработку корневого объекта с полимерным состоянием.

6 Резюме

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

использованная литература

Эрик Эванс. Дизайн, управляемый доменом. Перевод Чжао Ли, Шэн Хайяня, Лю Ся и др. People's Posts and Tele Communications Press, 2016. Винисиус Фейтоса Пачеко. Шаблоны микросервисов и лучшие практики: изучите шаблоны, такие как CQRS и источники событий, для создания масштабируемых , поддерживаемые и тестируемые микросервисы, Packt Publishing, 2018.