EventSourcing в иногда подключенных системах: что, если есть два сервера?
Я недавно ударился головой, пытаясь обойти эту проблему.
сценарий с одним сервером
У вас есть клиент, который иногда подключается к одному серверу.
Недавно я снова посмотрел видео Грега Янгса о иногда подключенных системах на skillmatter.com.
Там он утверждает, что лучший способ справиться с этим:
- У вас есть клиент, использующий поток событий.
- клиент сохраняет все команды, которые он выполнил в очереди
- Когда сервер снова становится доступным, клиент отправляет все команды и снова загружает результирующие события (локально, клиент удаляет события, которые были отправлены локально, поскольку сервер является единственным источником правды)
Теперь все в порядке, но у меня есть несколько более сложный сценарий - один с двумя серверами: Test и Production.
mutli server secnario
- Таким образом, клиент используется для создания какого-то шаблона
- затем он подключается к тестовому серверу и передает свои команды => у нас есть новая версия шаблона на тестовом сервере
- Время от времени клиент подключается к тестовому серверу и меняет шаблон
- Однако в какой-то момент этот шаблон должен быть опубликован на производственном сервере.
Вы также можете думать об этом как о сценарии git merge, где вы хотите перенести все свои изменения из разветвленного удаленного хранилища A в исходное удаленное хранилище B.
Проблема в:
- Как только клиент отправляет свои изменения в тестовую среду, команды исчезают - так как же он может протолкнуть любые изменения в производственную среду...
- Также: другой пользователь может быть использован для фактической публикации нового шаблона в Production. (Например, потому что публикация выполняется парнем, а не разработчиком)
Таким образом, я полагаю, что есть два решения этой проблемы: а) Сохраните поток команд и загрузите его также клиенту - но это будет противоречить тому факту, что в системах источников событий хранятся только события; б) иметь механизм для воссоздать команды из уже зафиксированных событий. Таким образом, клиент может просмотреть версию шаблонов в Production, чтобы увидеть, какие события там еще не были отправлены. Затем он создает команды и выполняет их.
Мои вопросы:
- Я думаю, что только б является жизнеспособным вариантом здесь?
- Не нарушает ли опция b какое-либо правило / принцип получения событий и / или cqrs?
- Есть ли другой и даже лучший способ сделать это?
Спасибо, ребята, за ваши мысли!
ОБНОВИТЬ
Спасибо, что поделились своими мыслями. Но, похоже, мне нужно кое-что прояснить - вещь с Test and Production.
Предположим, что мы создаем некоторую инфраструктуру приложений, такую как salesforce: вы можете - используя указатель и щелчок - определить ваше приложение с его сущностями, рабочими процессами и тому подобным. Конечно, вы бы сделали это в отдельной среде песочницы. Когда вы закончите работу с первой версией приложения, вы захотите перенести ее на рабочий сервер, чтобы ваши пользователи могли использовать приложение, которое вы "создали".
Теперь рассмотрим следующее: В процессе производства вы понимаете, что есть небольшая ошибка, и вы исправляете ее немедленно. Затем вы хотите перенести эти изменения обратно в тестовую среду.
Итак, теперь вопрос: что, черт возьми, является источником истины?
Мне нравится жаловаться на это, потому что большинство разработчиков знают это. В основном я вижу, что у меня есть два варианта:
- мерзавец
Одной из сред является книга рекордов. Так что в этом случае мне придется собирать все команды, и как только я обновляю производство, я нажимаю на команды. Это как мерзавец
- мерзавец слияния
Предположим, что обе системы являются "книгой рекордов". В этом случае мне нужно синхронизировать события, произошедшие в тестовой среде, и события, произошедшие в производственной среде (поэтому я получаю одно и то же определение приложения в Test and Production), поэтому события из Test не просто добавляются в eventstream. производства, но отсортированы в потоке событий производств в порядке, в котором они фактически произошли. Это как мерзавец слияния
Лично я предпочитаю опцию git merge, поскольку в обеих системах это приводит к одному и тому же порядку событий. И, конечно же, это позволило бы подключенным к разным клиентам клиентам использовать тот же подход для распределенного сотрудничества: предположим, что приложение, которое мы определили в Test и опубликовали в Production с использованием этого подхода к получению событий, затем используется несколькими подключенными время от времени клиентами для фактического сбора данных., Теперь несколько клиентов могут работать вместе в одной и той же совокупной корневой синхронизации друг с другом и сервером (как в системе peer2peer), сохраняя при этом тот же порядок потока событий.
Проблема может заключаться, однако, в том, что клиент синхронизирует событие e1 с сервером, но агрегат, которому соответствует это событие, уже обработал событие e2, которое произошло позже. Таким образом, обработка событий будет не в порядке.
Итак, мой вопрос: есть ли существенный недостаток в этом "git merge"?
1 ответ
Я думаю, что вы попали в сложившуюся ситуацию из-за вашего определения книги рекордов / правды.
Если производство является книгой рекордов, то именно здесь команды должны быть отправлены. В этом случае экземпляр теста в некоторых отношениях похож на экземпляр клиента; это становится песочницей, где вы можете попробовать что-то, но на самом деле это может не представлять "правду", когда дело доходит до перехода на следующую стадию. Таким образом, вы сохраняете команды в очереди и в конечном итоге доставляете эти команды вашему производственному экземпляру.
Если test является книгой рекордов для этих изменений, то вы не делитесь командами с производством, а делитесь событиями (или, возможно, проекциями, в зависимости от того, какая модель лучше подходит для вашего фактического варианта использования). Это несколько аналогично использованию микросервисов: тест - это микросервис, который поддерживает отправленные ему команды, а производство - это отдельный микросервис, который реагирует на события из теста - иными словами, производство зависит от модели чтения в тесте.
Обзор того, что Udi Dahan должен сказать об услугах, может помочь прояснить ситуацию
Сервис - это технический орган для определенных бизнес-возможностей. Любая часть данных или правила должна принадлежать только одному сервису.
Я полагаю, что, исходя из того, что вы используете "тест" и "производство", производственная система не имеет полномочий изменять данные, которые отправляются на тестирование; он просто использует представление этих данных. Который возвращает вас прямо к одному серверу (на самом деле: к единой книге записей).