流程管理器如何跟踪聚合之间的关联

时间:2017-03-04 20:31:21

标签: domain-driven-design cqrs event-sourcing

流程经理是否使用关联ID或特定于聚合的标识来跟踪它正在管理的进程

为了更清楚地说明一个例子,请考虑Saga on Sagas上的图2:

enter image description here

首先,Process Manager发送OrderConfirmed事件是对的?我(作为进程管理器)无法发送事件,只发出命令。或者我错了吗?

其次,流程管理器如何关联来自不同聚合的OrderCreated,SeatsReserved,PaymentReceived事件?是每个聚合尊重(并复制)的相关ID,还是特定标识符(例如SeatsReserved有一个引用订单聚合的订单ID)?

最后,如果是关联ID的情况,创建的人是谁?发出命令的客户端是PlaceOrder(order_id, correlation_id)吗?聚合是否接受PlaceOrder(order_id)之类的命令然后发出OrderCreated(order_id, corr_id)事件?或者,是负责这个的流程经理(以某种方式)?或者,相关id可能与此无关?

感谢您的帮助。

4 个答案:

答案 0 :(得分:6)

强烈建议在他的伟大着作Process Manager

中了解Implementing Domain-Driven Design设计模式的原始来源以及@Vaughn Vernon对该主题的处理

简而言之,Process Manager通过在启动特定进程时创建的Process实例同时处理多个进程。流程实例的ID是您的Correlation Identifier,它是流程持续时间内每个通信(命令/事件)的有效负载的一部分。 Process实例还有另一个术语,即Process Tracker。这个想法是一样的。

因此,在这种方法中,关注点明显分离。每个流程实例在其当前状态,重试,完成等方面负责其自己的流程。它是一个流程实例,负责发出ProcessFinished事件,因为它是"大脑"。

Process Manager的另一个名称是Long Running Process。因此,根据定义,最好是异步。

~Sergiy

<><

答案 1 :(得分:3)

我认为流程管理员是我域中的一等公民。流程管理器实例的Id通常充当相关ID。由于流程管理器是状态机,它实际上可以发布事件。好吧,我认为域事件系统事件不同。消息传递基础结构依赖于系统事件。这些是带有相关ID的那些,是的,它会被复制到相关的消息,但这是你的基础设施可以自动完成的。在我的Shuttle.Esb服务总线中,我这样做:复制标头和相关ID。

这就是为什么我也认为事物的过程方面几乎就是BC的一种类型。它通过发出命令然后响应相关事件来与构成过程一部分的各种BC进行交互。但是在基础架构(端点)层上,我可能想要发布一个事件,该事件表明特定进程已经放弃或完成或从一个步骤移动到下一个步骤。

修改

在我看来,流程管理器本身也是一个聚合。所有命令和事件都来自消息处理程序/应用程序层,以响应域中发生的情况。 来自域的任何事件本质上都是域事件,这些事件不一定适合系统到系统的通信。我想说“在集成/应用层”上比在基础设施(端点)层上更合适。

所有消息都在消息处理程序中处理。该消息处理程序充当集成点,并且必须直接或通过应用程序层与域交互。我的措辞可能没有那么明显:)

答案 2 :(得分:3)

免责声明:由于您提到的示例可互换地使用“saga”和“流程管理器”术语,我也会这样做。我知道saga和流程管理器模式的定义是不同的,但在业界我们看到 saga 这个词正在被许多流行的框架应用(从NServiceBus开始)。

看一下这个特例,它将是:

  • 从传奇中发布事件:它取决于。我强烈警告你不要建立任何教条式的方法,以便谁能做什么。你永远不会知道第二天会带来什么,你不应该只是“按书”做所有事情。如果ProcessManager编排整个过程,它可能很好地从一个聚合或上下文中消耗constraint事件,将命令发送到下一步,等待它产生确认事件以及整个过程完成时 - 发布自己的事件,在这种情况下,它通过一些UI魔术发送给客户。在这种方法中,我没有看到任何错误的。可能有更好的解决方案。

  • 通常情况下,saga id == correlation id并且它是一个人工短生命标识,在这种情况下,您确实需要跟踪相关性,并依赖您的基础设施将其从命令传递到命令处理程序端的事件。一旦saga实例被创建,你将需要生成这样的id(记住,saga具有逻辑和状态,并且每个运行的进程都有自己的状态)。或者你可以使用一些域对象id,就像你所指的那样,这可能是订单ID。但是,您需要注意在命令处理程序端将命令中的关联ID传递给事件。所以,saga id == correlation id == process state id,它也经常被用作saga状态持久性的主键。

您还可以在Chris Patterson's blog post中找到一篇关于使用状态机和MassTransit框架实现长期流程实现的好文章。

答案 3 :(得分:2)

首先,我应该说我的答案基于我的知识,经验以及我对如何在PHP上进行CQRS的看法

  

首先,Process Manager发送OrderConfirmed事件是对的吗?我(作为进程管理器)无法发送事件,只发出命令。或者我错了吗?

是。这是错误的。只有Aggregates加注Domain Events并执行Commands。也许Microsoft忘记显示发送到MarkOrderAsConfirmed command的{​​{1}}。

  

其次,流程管理器如何关联来自不同聚合的OrderCreated,SeatsReserved,PaymentReceived事件?是每个聚合尊重(并复制)的相关ID,还是特定标识符(例如SeatsReserved有一个引用订单聚合的订单ID)?

我使用参与此过程的OrderAggregate的ID。在这种情况下,相关ID可以与Aggregates的ID一对一地映射,它具有相同的寿命。

  

最后,如果是关联ID的情况,谁创建它们?是发出命令的客户端,如PlaceOrder(order_id,correlation_id)?是聚合接受像PlaceOrder(order_id)这样的命令,然后发出OrderCreated(order_id,corr_id)事件吗?或者,是负责这个的流程经理(以某种方式)?或者,相关id可能与此无关?

在这种情况下,我不会使用相关ID。我只将它们用于调试目的。 在我的架构中,为了消除代码重复,相关ID由命令的创建者(在Saga中)OrderAggregate生成(如果这是流程中的第一个命令,CommandDispatcher生成的所有Commands都不是Sagas生成的事件,而是存储在生成的事件中Metadata

更新的: 如何使用相关ID?您从事件存储中选择具有该相关ID的所有事件,这样您就可以"查看"这个过程。