CQRS - вышли из строя сообщения - PullRequest
0 голосов
/ 13 ноября 2018

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

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

Самый простой способ сделать это (для меня) - это поместить «что-то» перед каждым ES, который выбирает события и публикует (pub / sub) ихв очередях любой другой службы.

Это идеально, потому что каждая служба может подписываться на каждую понравившуюся тему, когда издатель событий выполняет свою работу и если служба недоступна, события по-прежнему доставляются.Мне кажется, это гарантирует высокую масштабируемость и доступность.

Моя проблема - очередь.Я не могу получить легко масштабируемую очередь, которая гарантирует порядок сообщений.На самом деле это гарантирует «немного вышедший из строя», по крайней мере, один раз при доставке: для ясности, это AWS SQS.

Итак, проблемы с заказом:

  • Заказ не гарантировансобытия из одного и того же потока событий.
  • Нет порядка для событий из одного и того же ES.
  • Нет порядка для событий из разных ES (разных служб).

Хотя я мог бы решить первые две проблемы, просто отслеживая «порядковый номер» событий, происходящих из одной и той же ES.Это будет сделано путем отслеживания последнего порядкового номера каждой темы, из которой мы потребляем события. Это должно быть легко для реагирования на события, а также для построения нашего прогноза.Затем, когда я вытаскиваю событие из очереди, если eventSequenceNumber > previousAppliedEventSequenceNumber + 1 я перезаписываю его (или делаю его невидимым в течение определенного времени).

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

Это потому, что когда я ожидаю событие 10 и на мгновение игнорирую событие 11, мне следует также игнорировать все события (из ES) с порядковыми номерами, которые следуют после этого события 11, пока событие 11 не появится снова иэто эффективно обработано.

Другие трудности были:

  • где отслеживать порядковый номер события для построения проекции.
  • как отслеживать событияпорядковый номер для построения проекции так, чтобы при его применении у меня был согласованный lastSequenceNumber.

Что мне не хватает?

PS: длятретью проблему думаю по следующему сценарию.У нас есть UserService и CartServiceCartService есть проекция, в которой каждый пользователь отслеживает товары в корзине.Каждая проекция корзины должна содержать также имя пользователя и другую информацию, полученную из события UserCreated, опубликованного из UserService.Если UserCreated идет после ProductAddedToCart, нормальный поток требует выбросить исключение, потому что пользователь еще не существует.

Ответы [ 2 ]

0 голосов
/ 18 ноября 2018

Основная проблема заключается в предположении, что мы можем получать сообщения В ПОРЯДКЕ ... Это ошибка в распределенных вычислениях ... Я предлагаю вам спроектировать не порядок сообщений в вашей системе.

Что касается ваших проблем,попробуйте использовать время UTC в теле / ​​заголовке сообщения, созданном originator , и попробуйте обойти эту точку данных.Порядковые номера потерпят неудачу, если у вас нет создателя центральной детерминированной последовательности (который будет немасштабируемой единой точкой отказа).

Использование Sagas / State Machine - это путь, который может помочь разобраться в(бизнес) организация мероприятий.

0 голосов
/ 13 ноября 2018

Что мне не хватает?

Вам не хватает потока - потребители извлекают сообщений из источников, вместо того, чтобы источники передавали сообщения потребителям.

Когда я просыпаюсь, я проверяю свою закладку, чтобы узнать, какие из ваших сообщений я прочитал последними, а затем спрашиваю вас, были ли они с тех пор.Если есть, я получаю их от вас по порядку (например, «документ сообщения»), а также записываю новые закладки.Затем я возвращаюсь в сон.

Основная цель push-уведомлений состоит в том, чтобы прервать период ожидания (тем самым уменьшая задержку).

Когда SQS действует как очередь, идея заключается в том, что вы читаете все сообщений в очереди одновременно.Если пробелов нет, вы можете заказать коллекцию, а затем приступить к их обработке и проверке.Если есть пробелы, вы либо ждете (оставляя сообщения в очереди), либо идете в хранилище событий, чтобы получить копии пропущенных сообщений.

Нет волшебства - если конвейер сообщений обещает "впо крайней мере один раз », тогда потребители должны предпринять шаги для распознавания повторяющихся сообщений по мере их поступления.

Если UserCreated следует после ProductAddedToCart, обычный поток требует выбросить исключение, поскольку пользователь несуществует еще.

Обзор Условия гонки не существуют , автор: Уди Даан: «Разница во времени в микросекундах не должна влиять на основные виды делового поведения.«

...