为 CQRS 实施包装 Masstransit 是一个好习惯吗? [关闭]

Posted

技术标签:

【中文标题】为 CQRS 实施包装 Masstransit 是一个好习惯吗? [关闭]【英文标题】:Is it a good practice to wrap Masstransit for CQRS implementation? [closed] 【发布时间】:2018-02-19 14:24:37 【问题描述】:

我宁愿有一个单独的 CommandBusEventBus 以及 ICommandHandler<TCommand>IEventHandler<TCommand> 以便 OrderEventHandler 类看起来像:

public class OrderEventHandler :
    IEventHandler<OrderPlaced>,
    IEventHandler<OrderRegistrantAssigned>,
    IEventHandler<OrderTotalsCalculated>,
    IEventHandler<OrderConfirmed>,
    IEventHandler<OrderExpired>,
    IEventHandler<SeatAssignmentsCreated>,
    IEventHandler<SeatAssigned>,
    IEventHandler<SeatAssignmentUpdated>,
    IEventHandler<SeatUnassigned>
 
    public void Handle(OrderPlaced @event)...
    .
    .
    .

一个可能的解决方案是在Masstransit 基础设施和我的CQRS 之间提供一个采用者(比如ConsumerToHandlerAdopter&lt;T&gt;,它只公开我通常需要的上下文细节)。

但由于我是 Masstransit 的新手,我无法理解以后可能需要处理的问题。

所以我的问题是: 通常是否值得封装 Masstransit 以便我处理自己的基础架构?

【问题讨论】:

您是否使用消息队列/总线来同步读取模型和写入模型?你能在这里看看我的问题吗? softwareengineering.stackexchange.com/questions/378205/… +1。 鲍勃叔叔:不要嫁给框架!哦,你可以使用这个框架——只是不要耦合它。保持距离。将框架视为属于架构外圈之一的细节。不要让它进入内圈。 【参考方案1】:

我们使用 MassTransit 广泛实施 CRQS,但仅用于命令处理。

多次讨论不使用消息传递基础架构来同步写入和读取模型的原因。主要原因是您有机会保持更改而不发布事件,因为这是两个不同的基础架构。除非你使用 DTC 之类的东西,否则你将无法保证模型之间的一致性。

此外,在这一点上,我们也更愿意远离“上帝处理程序”类。 MassTransit 特别擅长通过将每个消费者分离到一个单独的类来执行 SRP(单一责任原则)。

对于基于一般领域事件的集成(反应式事件处理),我们还使用 MassTransit。

您还可以拥有实现多个消息接口的事件,这样您将拥有更全面的事件处理:

public interface CustomerRegistered

    string FullName  get; 


public interface OrderPlaced

    string Reference  get; 
    List<OrderLine> Lines  get; 


public class NewCustomerOrderedStuff : CustomerRegistered, OrderPlaced

...


public class CustomerRegisteredConsumer : IConsumer<CustomerRegistered>

public class OrderPlacedConsumer : IConsumer<OrderPlaced>

这些消费者中的每一个都会有不同的关注点,并且可以生活在单独的有界上下文(服务)中。

【讨论】:

感谢一百万 @Alexey Zimarev,我正在使用 rabbitmq 作为传输层。我的目标是在传奇中代表我的聚合,只要它们变得一致,然后通过调用 aggregate.method() 发布返回的事件。聚合达到某种状态后我不需要它们,所以我可以删除它们。 我有几个项目使用 sagas 作为聚合。这工作得很好,但它没有单独的读写模型。同时,我为 EventStore github.com/alexeyzimarev/MassTransit.EventStoreIntegration 做了一个 saga 持久化,通过使用它,我可以拥有事件源 saga,使用投影构建读取模型,这些模型通过 EventStore 追赶订阅连接。 是的,在进行事件溯源时,拥有适当的事件存储非常重要。有些人为此目的使用无限期保留的 Kafka,但对此有不同的看法。当您使用事件溯源时,发布事件的问题会变得更糟,因为如果来自其他上下文的投影和事件消费者正在侦听同一总线,它将关闭重播事件的选项。 这是一种反应。这涉及将域事件转换为集成事件,并将它们写入集成流或将这些事件发布到某些消息总线。反应器消耗这些事件并在它们自己的有界上下文中产生必要的动作。您也可以将其称为“反应式 ACL”。 是的,这是一个潜在的问题,我对此没有真正的答案。我的观察是 RMQ 非常可靠。如果更改以事务方式持久化,然后我们将事件发布到总线,我们可以非常确定(尽管不是 100%)它确实发生了。我们运行 RMQ 多年,每天处理数百万条消息,从未遇到过问题。虽然这可能是网络问题,但在这种情况下,持久性也不起作用,除非它们位于完全不同的网络中。

以上是关于为 CQRS 实施包装 Masstransit 是一个好习惯吗? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

masstransit请求/响应:在消费者中获取调用者超时

如何写出简洁的 CQRS 代码?

Masstransit队列以公共汽车为前缀,后缀为随机字符串

具有事件溯源的 CQRS 模式具有用于读/写的单个数据库

MassTransit | 基于MassTransit Courier 实现 Saga 编排式分布式事务

怎样将微服务和无服务器相结合?用新型事件驱动型架构CQRS!