Как менеджер процессов отслеживает связь между агрегатами



Использует ли менеджер процессов корреляционные идентификаторы или агрегатные идентификаторы для отслеживания процесса, которым он управляет?



Чтобы выразиться яснее на примере, рассмотрим рисунок 2 на саге на сагах :



Введите описание изображения здесь



Во-первых, диспетчер процессов посылает событие OrderConfirmed неправильно, верно? Я (как менеджер процессов) не могу отправлять события, только выдавать команды. Или я ошибаюсь?



Во-вторых, как менеджер процесса соотносит OrderCreated, SeatsReserved, PaymentReceived события из разных агрегатов? Является ли это корреляционным идентификатором, который каждый агрегат чтит (и копирует), или это конкретные идентификаторы (например, SeatsReserved имеет идентификатор заказа, который ссылается на агрегат заказа)?



Наконец, если речь идет о корреляционных идентификаторах, то ктосоздает их ? Это клиент, который выдает команду, как PlaceOrder(order_id, correlation_id)? Это агрегат, который принимает команду типа PlaceOrder(order_id) и затем выдает событие OrderCreated(order_id, corr_id)? Или, может быть, это процесс менеджер (в некотором роде), который отвечает за это? В качестве альтернативы, возможно, корреляционные идентификаторы не имеют к этому никакого отношения?

Спасибо за любую помощь.

553   4  

4 ответов:

Настоятельно рекомендую ознакомиться с оригинальным источникомProcess Manager Design pattern, а также с трактовкой @Vaughn Vernon этой темы в его большой книге Implementing Domain-Driven Design

В двух словах, Process Manager имеет дело с несколькими процессами одновременно через экземпляры процессов, которые он создает при запуске определенного процесса. Id экземпляра процесса - это Ваш корреляционный идентификатор , который является частью полезной нагрузки каждого сообщения (команды / события) в длительности процесса. Существует еще один термин для экземпляра процесса, который называется Process Tracker. Идея та же самая. Таким образом, в этом подходе существует четкое разделение проблем. Каждый экземпляр процесса отвечает за свой собственный процесс с точки зрения его текущего состояния, повторных попыток, завершения и т. д. Это экземпляр процесса, который отвечает за излучение события ProcessFinished, так как это "мозг".

Другое название для процесса Диспетчере давно работает Процесс. Так что по определению лучше быть асинхронным.

~ Сергей

Я рассматриваюменеджера процесса как гражданина первого класса в моем домене. Id экземпляра process manager обычно выступает в качестве идентификатора корреляции. Поскольку менеджер процессов является государственной машиной, он может, в действительности, публиковать события. Ну, я рассматриваю доменные события как отличные от системные события. Инфраструктура обмена сообщениями опирается на системные события . Это те, которые будут нести идентификатор корреляции и, да, он будет скопирован в соответствующие сообщения, но это то, что ваша инфраструктура может делать автоматически. В моем челноке .Esb служебная шина я делаю именно так: копирую заголовки и корреляционный идентификатор.

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

Edit:

На мой взгляд, сам менеджер процессов также является агрегатом. Все команды и события будут исходить от обработчика сообщений / прикладного уровня в ответ на то, что происходит в домене. Любые события, которые действительно происходят из домена, по самой своей природе были бы событиями домена, и они не обязательно подходят для системы к системе связь. Я думаю, что было бы более уместно сказать "на уровне интеграции / приложения", чем на уровне инфраструктуры (конечной точки).

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

Отказ от ответственности: поскольку упомянутый вами пример использует термины" сага "и" менеджер процессов " взаимозаменяемо, я сделаю это также. Я знаю, что модели saga и process manager различны по определению, но в отрасли мы видим, что слово saga применяется многими популярными фреймворками (начиная с NServiceBus).

Глядя на этот конкретный пример, было бы:

  • Публикация событий из саги: это зависит. Я бы решительно предостеречь вас против построения любого догматического подхода к тому, кто что может делать. Вы никогда не можете знать, что принесет следующий день, и вы не должны просто делать все "по книге". Если ProcessManager организует весь процесс, он может очень хорошо использовать событие OrderConfirmed из одного агрегата или контекста, отправить команду на следующий шаг, дождаться, пока она произведет событие подтверждения, и когда весь процесс будет завершен - выдать свое собственное событие, которое в этом случае он отправил клиенту через некоторую магию пользовательского интерфейса. Я делаю не вижу ничего неправильного в этом подходе. Хотя, возможно, есть и лучшее решение.

  • Как правило, saga id = = correlation id, и это либо какая-то искусственная короткая жизнь, идентифицированная, и в этом случае вам действительно нужно будет отслеживать корреляцию и либо полагаться на вашу инфраструктуру, чтобы передать ее от команд к событиям на стороне обработчика команд. Вам нужно будет сгенерировать такой идентификатор, как только экземпляр saga будет создан (помните, что saga имеет логику и состояние, и каждый запущенный процесс имеет свое собственное состояние). Или вы можете использовать какой-то доменный идентификатор объекта, например, в случае, когда вы ссылаетесь на него, это может быть идентификатор заказа. Тем не менее, вам нужно будет позаботиться о том, чтобы пройти через идентификатор корреляции от команд к событиям на стороне обработчика команд. Итак, saga id = = correlation id = = process state id, который также часто используется в качестве первичного ключа для сохранения состояния saga.

Вы также можете найти хороший пост в блоге о длительном процессе реализация с использованием машин состояний и фреймворка MassTransit в блогеКриса Паттерсона .

Во-первых, я должен сказать, что я основываю свой ответ на моих знаниях, опыте и моем мнении о том, как следует делать CQRS на PHP

Во-первых, диспетчер процессов, отправляющий событие OrderConfirmed, ошибается, верно? Я (как менеджер процессов) не могу отправлять события, только выдавать команды. Или я ошибаюсь?

Да. Это неправильно. Только Aggregates поднимает Domain Events и выполняет Commands. Возможно, Microsoft забыла показать MarkOrderAsConfirmed command, который отправляется в OrderAggregate.

Во-вторых, как это происходит менеджер процессов соотносит события OrderCreated, SeatsReserved, PaymentReceived с различными агрегатами? Является ли это корреляционным идентификатором, который каждый агрегат чтит (и копирует), или это конкретные идентификаторы (например, SeatsReserved имеет идентификатор заказа, который ссылается на агрегат заказа)?

Я использую идентификаторы Aggregates, которые принимают участие в процессе. Корреляционный идентификатор в этом случае будет сопоставляться один к одному с идентификатором OrderAggregate, он имеет одинаковую продолжительность жизни.

Наконец, если речь идет о корреляционных идентификаторах, то кто их создает? Это клиент, который выдает команду, например PlaceOrder (order_id, correlation_id)? Это агрегат, который принимает команду типа PlaceOrder(order_id) и затем выдает событие OrderCreated (order_id, corr_id)? Или это менеджер процесса (в некотором роде), который отвечает за это? В качестве альтернативы, возможно, корреляционные идентификаторы не имеют к этому никакого отношения?

В этом случае я бы не стал использовать корреляционные идентификаторы. Я использую их для отладки только цели. в моей архитектуре , чтобы исключить дублирование кода, корреляционные идентификаторы генерируются создателем команды (в саге) или CommandDispatcher (Если это первая команда в процессе, как и все Commands, которые не генерируются Sagas) и хранятся в генерируемых событиях как Metadata.

обновление : Как использовать корреляционные идентификаторы? Вы выбираете все события из хранилища событий, которые имеют этот идентификатор корреляции, и таким образом вы можете "видеть" процесс.

Comments

    Ничего не найдено.