SAGA —— Process Manager
本文来源微软CQRS项目
Saga
saga的提出是为了会长时间运行的分布式事务(long-running process)的问题,避免使用分布式事务,使用分布式事务可以影响系统的性能和并发性。
saga,是一种基于补偿的消息驱动的用于解决长时间运行事务的一种解决方案。“SAGAS”
Process Manager
微软在CQRS项目中 提出了process manager术语。CQRS一个复杂的业务可能包含多个聚合跟,多个绑定上下文。业务流程里多个聚合跟之间有不同消息通信。
比如在会议系统里,购买座位流程涉及订单,预约,支付流程。它们合作才能完成购买流程。
1.不使用流程管理器 如下图
每个聚合都独自发送命令到另外的聚合跟执行流程的下一步。订单聚合发出MakeReservation命令给预定聚合为客户预定位置。位置完成预定之后 Reservation aggregate 发出aSeatsReserved事件通知 Order aggregate, 然后 Order aggregate 发出 付款命令给Payment aggregate.一旦完成付款订单发送订单完成通知给预定聚合,预定聚合完成座位预约并且客户被通知订单完成。
2.使用流程管理器 如下图
聚合跟之间不再直接处理消息, 通过流程管理器做消息中介,此模型下聚合不再需要知道下一步做什么,聚合内聚性更强。流程处理都在流程管理器中。
流程管理器不处理任何的业务逻辑,它只是进行消息路由。
逆处理
CQRS 在一次处理中,可以简化命令(Commond),命令处理器(ICommondHandler) 处理完命令,产生相应的(event) 最终由事件处理器(IEventHandler)处理完事件。
OrderProcessManager 考虑支付失败需要哪些逆事件。事件怎么组织。
我觉得需要下面几个事件
- 订单失败
- 归还座位
事件发生的组织方式也可以有两种
- 直接在支付失败的时候发送订单失败和归还座位的命令
- 发出归还座位的命令,在归还座位的EventHanler里 再发出订单失败的命令。
伪Code
public class RegistrationProcessManager : IEventHandler, IEventHandler , IEnvelopedEventHandler , IEventHandler , IEventHandler , ICommandHandler { public void Handle(OrderPlaced @event) { this.AddCommand(new Envelope (seatReservationCommand) { TimeToLive = expirationWindow.Add(TimeSpan.FromMinutes(1)), }); } } public void Handle(PaymentCompleted @event) { this.AddCommand(new ConfirmOrder { OrderId = this.OrderId }); } public void Handle(OrderConfirmed @event) { this.ExpirationCommandId = Guid.Empty; this.Completed = true; this.AddCommand(new CommitSeatReservation { ReservationId = this.ReservationId, ConferenceId = this.ConferenceId }); } }
。。。。。。
可以SAGA是组织了一系列的EventHandler,正常EventHandler处理完可以理解为一个CQRS流程结束,这里的EventHandler是发出下一步要处理的命令。