RabbitMQ 暂时宕机时的 Rebus 重试策略

Rebus retry policy when RabbitMQ is temporarily down

我有一个 dockerized 微服务架构,我在其中使用 Rebus 和 RabbitMQ 作为消息总线。

一个容器是 运行ning RabbitMQ。其他容器是通过 Rebus/RabbitMQ.

相互通信的 运行ning 服务

我希望我的解决方案能够适应容器重启,因此如果例如 RabbitMQ 容器重启,我希望其他服务不会受其影响。 我希望在 RabbitMQ 关闭时发送的消息排队等待 Rebus 传递 在发送服务中,并在 RabbitMQ 连接恢复时传送。

验证我运行这个测试场景:

  1. 服务A通过Rebus和RabbitMQ向服务B发送消息。效果不错。
  2. 我停止了 RabbitMQ 容器。
  3. 服务A通过Rebus和RabbitMQ向服务B发送消息。这失败了,因为 RabbitMQ 不可用。
  4. 我再次启动 RabbitMQ 容器。
  5. 我可以看到我的服务中的 Rebus 在启动时会自动重新连接到 RabbitMQ。符合预期。
  6. 现在 RabbitMQ 连接已恢复,我希望 Rebus 将待处理消息从服务 A 发送到服务 B,但它没有。

这不是 Rebus 的预期行为吗?如果没有,我可以启用此功能吗?

我已阅读此主题https://github.com/rebus-org/Rebus/wiki/Automatic-retries-and-error-handling 并尝试像这样配置 Rbus:

Configure.With(...)
    .Options(b => b.SimpleRetryStrategy(maxDeliveryAttempts: 10))
    .(...)

但运气不好。

您正在配置的“传递尝试”是您如何配置 Rebus 在放弃之前应该尝试使用接收到的消息的次数(即将其移至错误队列)。

如果 Rebus 失去与代理的连接,它将无法在整个中断期间接收任何东西,因此停止 RabbitMQ 应该有效地暂停所有消息处理(可能在所有正在处理的消息中有一些例外) RabbitMQ 消失的瞬间)。

因为没有 Rebus 处理程序 运行 那么,当 RabbitMQ 关闭时,您将不得不处理从其他地方发送的传出消息,例如喜欢来自 Web 请求的消息 sent/published。

(...) I expect that messages sent while RabbitMQ is down are queued up for delivery by Rebus (...)

...但是 Rebus 无法排队任何东西,因为 RabbitMQ 已关闭 (*)。

在这种情况下,Rebus 的自然做法是让您(调用者)负责决定如何处理该问题。

在 .NET 中,您通常通过向您抛出异常来做到这一点。

这让您可以选择

  • 执行一些替代操作,或者
  • 再试几次,或者
  • 任何在特定情况下有意义的东西

在这种情况下,一种在系统中构建弹性的简单方法是使用类似 Polly 的方法,在可能失败的情况下尝试多次发送传出消息。

我希望这是有道理的。如果需要详细说明,请告诉我。


(*) 当然,Rebus 可以“欺骗”并在内存中排队传出消息,但这会使您很难编写有弹性的代码,因为您不知道传出消息是否已经安全交付给经纪人,或者它是否只是坐在内存中等待保存在某个地方。