CQRS之旅——旅程3(订单和注册限界上下文) (9)

CQRS之旅——旅程3(订单和注册限界上下文)

Carlos(领域专家)发言:

稍后,当团队试图使用Azure服务总线作为消息传递基础设施时,发现了一个问题。Azure服务总线不支持带有数据库的分布式事务。有关这个问题的讨论,请参阅第5章“准备发行V1版本”。

在注册限界上下文中,惟一的事件订阅者是RegistrationProcessManager类。它的Router订阅者从订阅事件总线订阅,来处理特定的事件,下面的代码示例展示了RegistrationProcessManager类。

我们使用了术语Handler来指代处理命令和事件并将它们转发给聚合实例的类,使用术语Router来指代处理事件和命令并将它们转发给流程管理器实例的类。 public void Handle(ReservationAccepted @event) { var repo = this.repositoryFactory.Invoke(); using (repo as IDisposable) { lock (lockObject) { var process = repo.Find<RegistrationProcessManager>(@event.ReservationId); process.Handle(@event); repo.Save(process); } } }

通常,事件处理程序方法获取流程管理器实例,将事件传递给流程管理器,然后保存流程管理器实例。在本例中,IRepository实例负责持久化流程管理器实例,并负责将任何命令从流程管理器实例发送到命令总线。

使用Azure服务总线(Service Bus)

为了传输命令和事件,团队决定使用Azure服务总线来提供底层消息传递基础设施。本节描述了系统如何使用Azure服务总线,以及团队在设计阶段考虑的一些替代方案和权衡。

CQRS之旅——旅程3(订单和注册限界上下文)

Jana(软件架构师)发言:

Contoso的开发团队决定使用Azure服务总线,因为它为会议管理系统中的消息传递场景提供了开箱即用的支持。这将最小化团队需要编写的代码量,并提供健壮的、可伸缩的消息传递基础设施。该团队计划使用重复消息检测和保证消息排序等功能。要了解Azure服务总线和Azure队列之间的区别,请参阅MSDN上的“Microsoft Azure Queues and Microsoft Azure Service Bus Queues - Compared and Contrasted”。

下图显示了命令和事件消息如何在系统中流动。MVC控制器和领域对象使用CommandBus和EventBus实例将BrokeredMessage消息发送给Azure服务总线中的两个Topic之一。接收消息时,消息处理类是CommandProcessor和EventProcessor实例,CommandProcessor类确定哪个处理程序应该接收命令消息,EventProcessor类确定哪些处理程序应该接收事件消息。后者使用SubscriptionReceiver类从Topic获取事件。处理程序实例负责调用领域对象上的方法。

Azure服务总线的Topic可以有多个订阅者。Azure服务总线将发送到Topic的消息传递给它的所有订阅者。因此,一条消息可以有多个接收者。

在最初的实现中,CommandBus和EventBus类非常相似。Send方法和Publish方法之间的惟一区别是,Send方法期望消息被包装在Envelope类中。Envelope类允许发送方指定消息传递的时间延迟。

事件可以有多个接收者。在上图的示例中,ReservationRejected事件被发送到RegistrationProcessManager、WaitListProcessManager和另一个目的地。EventProcessor类通过检查已注册的处理程序列表来标识收到事件的处理程序列表。

命令只有一个接收者。在上图中,MakeSeatReservation被发送到可用座位(SeatsAvailability)聚合。只有一个为该命令注册的处理程序。CommandProcessor类通过检查已注册的处理程序列表来标识收到命令的处理程序。

这一实现带来了一些问题:

如何将命令的传递限制为单个接收?

如果CommandBus和EventBus类如此相似,为什么要分别使用它们呢?

这种实现的可伸缩性如何?

这种实现的健壮性如何?

怎么划分Topic和订阅的粒度?

命令和事件如何序列化?

下面几节将讨论这些问题。

将命令传递给单个接收者

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfsgw.html