Saga设计模型——领域驱动设计

一、Saga种类说明

常用的Saga包含两类:协同式和编排式。前者把流程的走向与协调全盘由事务的参考者来完成,比如最简单的场景:下单同时对库存进行扣减,订单服务本地事务完成后就把事件消息发送给库存服务,库存服务如果本地事务处理失败则由它将回滚的消息发送给订单服务。虽然整个流程当中订单服务与库存服务并没有产生耦合,但由于没有一个总的事务协调者,一旦服务参与者多起来那业务流程的可理解性就非常差,出了问题也不好定位。第二类为编排型事务也是我们本章要主要介绍的,通过把Saga的执行顺序交由一个集中的Saga编排器,由它指挥并决策业务的流向,相对于协同式整个流程要清晰很多。除非您使用的是足够成熟的第三方的框架,要不然集中式Saga也可能会存在事务参与者不清晰的问题,比如本文我们要介绍的Saga就会有类似的问题,毕竟以个人的精力很多事情的确无法做到极致,有牺牲也很正常。基于消息式的Saga很多时候你并不知道谁订阅了消息,所有的消费情况都体现在代码中,非常不方便后续的业务扩展以及代码阅读。个人在使用的时候偷了一个懒:通过图形文档的方式说明整个事务的走向包括会由谁发送命令,由谁来订阅事件,也就是把流程的逻辑定义与代码进行了分离,好的方式当然是把这些信息作为元数据来用。

二、基于编排式的设计思想

这里使用了四个设计原则:1)方便起见Saga会和全局事务发起的一起部署,这样就不用花费精力考虑如何独立部署Saga服务;2)Saga所有的服务遵循了这样的一个模式:发送命令,接受事件。也就是说Saga只向外发布领域命令,事件参与者执行完本地事务后发送领域事件并由Saga进行订阅,各服务间使用消息队列进行解耦;3)Saga的实现也被分为应用服务和领域实体。所有的命令其实都是由Saga领域实体在处理事件后生成的,在应用服务中调用“RabbitMQ”的客户端进行发送;4)只存储命令消息,不存储事件。

三、代码实现

根据上述的模式说明您会发现发布命令与事件并不需要进行代码的说明,通过RabbitMQ的客户端即可搞定。由于我们并不会将Saga实现为一个框架,所以也不涉及到框架内部复杂的逻辑代码,那么唯一需要介绍的是Saga如何与业务集成,这也是为什么我为本章所起的标题是“Saga设计模式”。

1、命令分发与处理

我们把发送命令和事件的组件称之为“命令总线”或“事件总线”,这样的封装在使用的时候不用使用者(一般是工程师)考虑消息队列使用的各种细节也可以实现组件的复用,毕竟您使用Saga的场景可能不只一个。

熟悉RabbitMQ的朋友都知道想要让消费者正确的收到消息我们可以使用“Topic”模式,相当于给消息一个路由的策略,Exchange会根据Topic的名称把消息投递到某个队列中,而消费者通过这与个队列进行绑定就可以进行消费了。针对命令总线我们仍然这用这个模式,我们把Topic命名为“command.bus”。由于命令的特性是只有一个消费者,所以不论消费者启动了多少个实例,反正只要有一个能消费就行。这样做以后……这样做就什么都做不了了,这个思路是错误的。以上图为例,因为所有命令型的消息的Topic都是“command.bus”,很有可能这些命令全被“事务参与者2”消费了,他处理“命令1”自然没问题,“命令2”他可真搞不定了。所以,很可惜,“Topic”模式根本不适用。

让我们再翻翻其它的模式,“Direct”貌似也差点意思,搞不定!那只能使用“Fanout”做点文章了。所以正确的方式应该是使用这个模式,消息被发出去后让所有的事务参与者都去订阅,然后在每个事务参考者内部维护一个类似路由表的东西,可以完成“通过某个命令的名称便可知道应该哪段代码来处理这个命令”的需求,正好是一个键值对:键是命令的名

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值