【问题标题】:Axon Framework: Saga project with compensation events between two or three microservicesAxon 框架:具有两个或三个微服务之间的补偿事件的 Saga 项目
【发布时间】:2023-04-03 07:09:02
【问题描述】:

我有一个关于 Axon Saga 的问题。我有一个项目,我有三个微服务,每个微服务都有自己的数据库,但是两个“从”微服务必须将他的数据共享给“主”微服务,因为我想使用 Axon Saga。我已经问了一个关于赔偿的问题,当出现问题时,我必须自己处理赔偿,可以,但并不理想。目前我正在使用 DistributedCommandBus 在微服务之间进行通信,这样做有好处吗?我使用的是 Choreography Saga 模型,所以它现在的样子如下:

  1. Master -> 发送命令 -> Slave1 -> 处理事件
  2. Slave1 -> 发回命令 -> Master -> 处理事件
  3. Master -> 发送命令 -> Slave2 -> 处理事件
  4. Slave2 -> 发回命令 -> Master -> 处理事件

如果出现问题,则补偿命令/事件会倒退。

我的问题是,有没有人对 Axon 做过类似的事情,有补偿,最好的做法是什么?如何重试 Saga 进程?使用 RetryScheduler?如果可以的话,添加一个 github repo。

谢谢,马特

【问题讨论】:

    标签: java spring-boot saga axon


    【解决方案1】:

    首先,让我回答你的主要问题:

    我的问题是有人用 Axon 做过类似的事情吗?

    简而言之,是的,因为这是 Sagas 的主要用例之一。 根据经验,我想说 Saga 可用于协调以下之间的复杂业务交易

    1. 几个不同的聚合实例
    2. 几个有界上下文

    从表面上看,您似乎已经选择了委托复杂业务交易的选项二。

    需要注意的是,当您使用 Sagas 时,您应该非常有意识地处理任何异常和/或命令调度结果。

    因此,如果您从“Master”向“Slave 1”发送命令而后者操作失败,则此结果将返回到 Saga。 因此,这为您提供了重试操作的第一个选项,我建议您使用补偿操作。 最后,关于补偿动作,我说的是调度一个命令来触发它。

    如果您不能依赖调度命令的直接响应,那么在 Saga 中重试/重新安排消息将是一个合理的第二选择。

    为此,Axon 拥有EventSchedulerDeadlineManager。 请注意,两者中的前者发布了一个事件供所有人查看。 后者在单个 Saga 实例的上下文中安排 DeadlineMessage,从而限制了谁可以看到正在发生的重试。

    通常情况下,DeadlineManager 将是我的首选操作模式,除非您要求所有人都可以看到此“重新安排操作”。 仅供参考,请查看this 页面以获取EventScheduler 信息和this 页面以获取DeadlineManager 信息。

    示例更新

    这里有一些伪代码来感受一下 Saga 事件处理程序中的补偿操作是什么样的:

    class SomeSaga {
    
        private CommandGateway commandGateway;
    
        @SagaEventHandler(assocationValue = "some-key")
        public void on(SomeEvent event) {
            // perform some checks, validation and state setting, if necessary
            commandGateway.send(new MyActionCommand(...))
                          .exceptionally(throwable -> {
                                             commandGateway.send(new CompensatingAction(...));
                                         });
        }
    }
    

    【讨论】:

    • 您能否告诉我们如何使用此框架实现补偿交易?
    • 这里的关键在于“行动”这个词。 “命令 == 动作”,所以补偿动作只不过是发送一种命令。事实上我不在那里使用命令,因为一个动作是什么在很大程度上取决于你自己的领域。
    • 所以更具体地说,您将捕获异常并在 catch 块或 CompletableFuture#exceptionally 方法中执行补偿操作。例如,这种补偿动作可以是发送一个命令来回滚更改。因此,您可以使用 CommandGatewayCommandBus 来实现这一目的,因为它们用于调度命令。
    • 您可能已经注意到,这里没有真正的框架魔法可以帮助您。这很简单,因为 Axon Framework 无法知道您需要执行什么操作才能回滚。它只是为 CQRS、DDD 和事件溯源提供基础设施,并以消息传递为基础。解决此问题的关键是它的消息传递基础,以便能够调度补偿操作。
    • 感谢您的澄清。现在已经很清楚了。我期待 Axon 会免费为我们做这件事。您能否分享一些关于如何使用 Axon 完成补偿事务的示例代码,这将非常有帮助。
    【解决方案2】:

    我不知道您的确切用例,但是从这个和您之前的问题中,我得到了您想要回滚的印象,或者在这种情况下撤消,如果一个事件处理程序无法处理它。

    一般来说,您可以做一些事情。您可以查看首先应用事件的聚合是否具有或可以拥有信息来检查“从”微服务是否应该能够在应用之前处理该事件。如果这不切实际,从属微服务也可以直接在事件总线上应用“失败”事件,以通知系统的其余部分发生了需要处理的失败状态:

    https://docs.axoniq.io/reference-guide/implementing-domain-logic/event-handling/dispatching-events#dispatching-events-from-a-non-aggregate

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-15
      • 2020-09-17
      • 1970-01-01
      • 2016-08-10
      • 2018-09-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多