Предположим, у нас есть 3 разных сервиса, создающих события, каждый из которых публикует в собственном хранилище событий.
Каждый из этих сервисов использует события сервисов других производителей.Это связано с тем, что каждый сервис должен обрабатывать события другого сервиса И создавать свою собственную проекцию.Каждый из сервисов работает на нескольких экземплярах.
Самый простой способ сделать это (для меня) - это поместить «что-то» перед каждым ES, который выбирает события и публикует (pub / sub) ихв очередях любой другой службы.
Это идеально, потому что каждая служба может подписываться на каждую понравившуюся тему, когда издатель событий выполняет свою работу и если служба недоступна, события по-прежнему доставляются.Мне кажется, это гарантирует высокую масштабируемость и доступность.
Моя проблема - очередь.Я не могу получить легко масштабируемую очередь, которая гарантирует порядок сообщений.На самом деле это гарантирует «немного вышедший из строя», по крайней мере, один раз при доставке: для ясности, это AWS SQS.
Итак, проблемы с заказом:
- Заказ не гарантировансобытия из одного и того же потока событий.
- Нет порядка для событий из одного и того же ES.
- Нет порядка для событий из разных ES (разных служб).
Хотя я мог бы решить первые две проблемы, просто отслеживая «порядковый номер» событий, происходящих из одной и той же ES.Это будет сделано путем отслеживания последнего порядкового номера каждой темы, из которой мы потребляем события. Это должно быть легко для реагирования на события, а также для построения нашего прогноза.Затем, когда я вытаскиваю событие из очереди, если eventSequenceNumber > previousAppliedEventSequenceNumber + 1
я перезаписываю его (или делаю его невидимым в течение определенного времени).
Но оказывается, что при использовании этого решения оно разрушит производительность, когдасобытия производятся с высокой скоростью (я могу использовать тайм-аут видимости или другие вещи, результат должен быть таким же).
Это потому, что когда я ожидаю событие 10 и на мгновение игнорирую событие 11, мне следует также игнорировать все события (из ES) с порядковыми номерами, которые следуют после этого события 11, пока событие 11 не появится снова иэто эффективно обработано.
Другие трудности были:
- где отслеживать порядковый номер события для построения проекции.
- как отслеживать событияпорядковый номер для построения проекции так, чтобы при его применении у меня был согласованный
lastSequenceNumber
.
Что мне не хватает?
PS: длятретью проблему думаю по следующему сценарию.У нас есть UserService
и CartService
.У CartService
есть проекция, в которой каждый пользователь отслеживает товары в корзине.Каждая проекция корзины должна содержать также имя пользователя и другую информацию, полученную из события UserCreated
, опубликованного из UserService
.Если UserCreated
идет после ProductAddedToCart
, нормальный поток требует выбросить исключение, потому что пользователь еще не существует.