当前位置: 首页 > 后端技术 > PHP

SagaofEventConsumers-事件追踪

时间:2023-03-29 22:29:44 PHP

本文转载自【WhyDecoupled】:https://codedecoupled.com/php...什么是SagaSaga是一种处理长业务流程的设计模式。这里的长度不是时间的长短,而是指一个业务流程由于跨域而涉及到的域宽度。所以一个Saga的处理周期可能是一周、一个小时、一分钟甚至几秒,跟时间无关。为什么使用Saga在DDD(DomainDriven)中,我们使用聚合来构建以自我为中心的模型。聚合具有很好的自我保护能力,外界只能通过Command来调用聚合的接口。看起来这是一个很好的设计,但是业务需求层出不穷。当一个业务流程需要多个聚合参与时,我们可以使用Saga。让我们举一个简单的例子。有两个独立的聚合,分别是OrderAggregate和InventoryAggregate:OrderAggregatePlaceOrderCommand:触发OrderPlacementConfirmedEvent事件。InventoryAggregateCheckInventory:触发InventoryAvailableEvent或InventoryNotAvailableEvent事件。订单聚合对外提供两个接口:PlaceOrderCommand:该接口用于提交用户订单。库存聚合提供了一个对外接口:DeductInventory:该接口用于检查库存是否充足。以上两个聚合体独立存在,没有合作关系。订单聚合用于提交用户订单,库存聚合用于查看库存。此时调用PlaceOrderCommand不会检查库存,但是业务需求在提交订单时肯定会要求库存充足。这时候订单聚合和库存聚合就必须相互配合,所以我们可以使用Saga。首先,我们需要修改订单聚合接口:OrderAggregatePlacingOrderCommand:触发OrderPlacingEvent事件。ConfirmOrderPlacementCommand:触发OrderPlacementConfirmedEvent事件。修改后的订单聚合对外提供了两个接口:PlacingOrderCommand:该接口用于提交用户订单。ConfirmOrderPlacementCommand:该接口用于确认用户订单的提交。那么我们就可以使用Saga来实现业务需求了:}publicfunctiononInventoryAvailableEvent(Inventory$evAvailableEvent){$this->confirmOrderPlacementCommand->handle($event->orderAggregateId);}}我们需要记住,Saga是一个业务流程的模型,但它没有任何逻辑代码,它只是指导聚合顺序之间的API调用。在应用程序级别,它就像一个简单的事件侦听器。我们经常可以用一个简单的流程图来梳理Saga,比如PlaceOrderSaga:上面实现Saga的代码只是Saga的一个原型。在实现Saga设计模式时,需要注意以下几点:排序和去重合二为一在事件驱动的系统中,基础设施的不确定性会导致事件信息的顺序颠倒,内容重复。例如,在使用AWSSQS时,如果不使用FIFQ队列,则无法控制消息发送的顺序。再比如在RabbitMQ中,如果一条消息没有及时消化,可能会重发同一条消息。基于以上两点,在实现Saga的时候,一定要兼具排序和去重功能,这样我们的应用层API才会没有后顾之忧。补偿行为Saga运行过程中出现异常怎么办?就像我们的例子,如果最后一步的confirmOrderPlacementCommand因为某种执行失败了怎么办?此时的存货已经扣除。如果不处理,库存肯定与订单不匹配,那将是一场灾难。Saga在实现的时候必须支持补偿行为,就像数据中的回滚行为一样,但是它不依赖于数据库来实现。添加补偿行为后,PlaceOrderSaga的代码更新为:}publicfunctiononInventoryAvailableEvent(InventoryAvailable){$this->confirmOrderPlacementCommand->handle($event->orderAggregateId);}公共函数onInventoryAvailableEventFailed(InventoryAvailableEvent$event){$this->increaseInventoryCommand->handle($event->inventoryAggregateId);如果confirmOrderPlacementCommand失败,也就是onInventoryAvailableEvent失败,我们在onInventoryAvailableEventFailed中将库存添加回来。注意事项Saga是一种易于理解的设计模式,在跨域场景中可以成为非常强大的解决方案。最后,我们需要注意一点,上面没有提到,那就是如果补偿行为本身失败了,我们该如何处理呢?如果你的基础设施能够保证补偿行为的稳定性,那就太好了。如果不行,只能及时手动修复,也就是我们上面用的方法。本文转载自【WhyDecoupled】:https://codedecoupled.com/php...,如果你也对TDD、DDD和简洁代码感兴趣,请关注公众号【WhyDecoupled】,一起探讨一起软件开发的方式。