如何保证在服务响应用户后发送事件?

How to make events guaranteed send after service responded to user?

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

与任务管理器通信

通信架构是:

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

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

通信可视化图:

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

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

这不是一个微不足道的问题,但幸运的是,对于解决此类问题的方法已经达成了一些共识 - 并且出现了一些通用语言,您将在这个答案中找到这些语言以帮助您进行搜索。这些想法通常属于 CAP theorem. But a practical place to start is with something called Transactional Outbox (see https://microservices.io/patterns/data/transactional-outbox.html)

的主题

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

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

地铁:https://masstransit-project.com/articles/outbox.html 有许多概念被组合在一起以创建一个在内存中的事务发件箱 - 有点。基本前提是 RabbitMQ 持久化需要发生的操作(以队列中消息的形式)。一旦操作为 'complete',您只能确认消息。 MassTransit 采用了一些策略来实现这一目标。同样,您可以利用此框架,或检查它以推出您自己的类似解决方案。

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

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

希望这能让你入门。