【问题标题】:How to make events guaranteed send after service responded to user?如何在服务响应用户后保证事件发送?
【发布时间】:2021-04-27 14:49:14
【问题描述】:

我需要使用外部任务管理器构建一个长时间运行的任务服务。 它通过 2 个通道与用户通信:http\websocket 和通过 http\RMQ 与任务管理器

通信模式是:

  • 用户发送任务创建请求
  • 我的服务将其发送给外部任务管理器
  • 接收任务管理器的响应并进行一些任务数据后处理
  • 使用“taskId”向用户发送响应
  • 用户等待任务事件并更新任务状态

问题是在某些情况下(当任务失败或它非常简单时)任务事件非常快地到达我的服务,直到用户的请求完成,因为后处理可能比任务执行需要更长的时间(尤其是在失败的情况下)。

所以问题是:如何在我的服务响应用户后保证发送事件? 现在我只是使用延迟,但猜测这不是最佳实践,因为当连接不佳时,我的延迟可能不够。

沟通的视觉图:

【问题讨论】:

    标签: architecture rabbitmq


    【解决方案1】:

    如果我理解您的问题,可以归结为这一行:所以问题是:如何在我的服务响应用户后保证发送事件?

    这需要一些其他机制来允许即发即弃,但要保证消息传递;并且,完成状态(成功或失败)会以某种方式传递回给用户。

    这不是一个微不足道的问题,但幸运的是,已经就解决此类问题的方法达成了一些共识 - 并且出现了一些通用语言,您可以在此答案中找到它们以帮助您进行搜索。这些想法通常属于CAP定理的主题。但是一个实际的起点是使用称为事务发件箱的东西(请参阅https://microservices.io/patterns/data/transactional-outbox.html

    想到了两个开箱即用(请原谅双关语)的解决方案:

    DotNetCore 的 CAP:https://cap.dotnetcore.xyz/ 即使您不是在 DotNetCore 中进行开发,您也可以在您的实现语言中找到类似的东西,或者推出您自己的类似解决方案。基本思想是使用数据库来捕获用户操作。只有当动作被提交到数据库时,该动作才被认为已被消化。然后第二个操作保证所有持久的操作都遵循:例如发送该操作的所有事件。在“完成”时,一个动作被标记为完成。对于永远不会成功的操作,仪表板会提醒您进行干预。这是使用数据库的事务性发件箱的实现。这就是一般的想法。

    大众运输:https://masstransit-project.com/articles/outbox.html 有许多概念被汇集在一起​​,以创建一个存储在内存中的事务发件箱 - 有点像。基本前提是 RabbitMQ 持久化需要发生的动作(以队列上消息的形式)。您只有在操作“完成”后才确认消息。 MassTransit 采用了一些策略来实现这一点。同样,您可以利用此框架,或检查它以推出您自己的类似解决方案。

    这两种解决方案都需要幂等性。也就是说,因为任何时候都可能发生故障,并且整个过程可以重新运行(动作、事件等),所以它们需要是可重复的,没有重复或副作用。

    在我当前的项目中,我们使用 CAP DotNetCore 进行交付,一定不能失败。

    希望这能让你开始。

    【讨论】:

    • 感谢您的回答,看来这就是我想要的。还要感谢您提供的链接,因为我的项目在 .NET 上是准确的 :)
    • 太棒了。请将其标记为已接受的答案。如果它是公认的答案:-)
    • 是的,这需要一些时间,直到问题被标记为已回答:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-11
    • 2019-03-29
    • 1970-01-01
    • 1970-01-01
    • 2016-07-13
    • 1970-01-01
    • 2022-12-09
    相关资源
    最近更新 更多