Как обработать несколько сущностей, переданных из REST-API в саге, с использованием Event-Sourcing (Axon Framework)? - PullRequest
1 голос
/ 05 июня 2019

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

Обстоятельства следующие:

У меня 3 микросервиса, м1, м2 и м3

Пользователь вводит данные для 3 сущностей e1, e2, e3 в GUI, которые обрабатываются и сохраняются с помощью m1, m2, m3 соответственно, поэтому m1-> e1, m2-> e2, m3-> e3

Теперь о необходимости саги:

e1 не может существовать без e2, а e2 не может существовать без e3.

Таким образом, все 3 сущности должны быть успешно созданы их соответствующими службами, и в случае неудачи саге необходимо выполнить компенсирующие транзакции для обеспечения согласованности. Сначала m1 создает e1, испускает e1CreatedEvent, а оркестратор отправляет команду createE2Command в качестве реакции на это и т. Д.

Теперь мои проблемы:

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

Например, m1 создает команду createE1Command и добавляет к ней информацию из e1, затем, после ее успешного создания, оркестратор инициирует команду createE2Command, а затем добавляет информацию для e2 в эту команду, прежде чем отправить ее .... для этого в случается, информация для e2 должна храниться как-то до тех пор, пока она не понадобится.

Пример кода:

@Saga
public class ManagementSaga{

@Autowired
private transient CommandGateway commandGateway

@StartSaga
@SagaEventhandler
public void handle (e1CreatedEvent e1CreatedEvent){


  commandGateway.send (new CreateE2Command (e1CreatedEvent.Id, **HERE NEEDS TO BE THE INFO THAT THE USER CREATED PREVIOUSLY**)}}

Я просто создаю объект, который содержит информацию для этих трех сущностей? Это действительно неправильно.

Теперь я понимаю, что, может быть, очень плохо выбирать такую ​​модель предметной области, и, возможно, следует избегать ее, если это возможно, но для наглядности: -)

1 Ответ

2 голосов
/ 06 июня 2019

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

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

Чтобы в любом случае дать вам ответ, который, как мы надеемся, более полезен, чем «это зависит», вы можете получить один результат взаимодействия в нескольких командах или даже запросах. Во всех случаях не требуется сага.

Примите один запрос с информацией о E1, E2 и E3. Затем в своем контроллере отправьте команды для создания E3, основываясь на результатах этой команды, создайте E2 и, наконец, создайте E1. Никакая информация не должна быть "кэширована". Информация о запросе доступна на протяжении всего процесса. Однако такой подход не является транзакционным. Если служба аварийно завершает работу, она может привести к неполному выполнению процесса.

Альтернативой является наличие обработчика команд, который регистрирует первоначальное намерение пользователя. Это не создание E1, или E2 или E3, а то, что охватывает все три. Событие, которое генерирует процесс, запускает Saga для выполнения каждого шага индивидуально, используя события этих шагов для запуска следующего шага. Этот процесс является транзакционным с характеристиками возможной согласованности.

Надеюсь, это имело смысл. Тем не менее, я бы серьезно пересмотрел модель / дизайн сервисов, чтобы они больше фокусировались на процессе (этапах), а не на объектах (состоянии). Я видел слишком много проектов Microservices, терпящих неудачу из-за ориентированного на сущность проекта ...

...