【问题标题】:Rebus retry policy when RabbitMQ is temporarily downRabbitMQ 暂时关闭时的 Rebus 重试策略
【发布时间】:2020-08-01 00:02:45
【问题描述】:

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

一个容器正在运行 RabbitMQ。其他容器正在运行通过 Rebus/RabbitMQ 相互通信的服务。

我希望我的解决方案能够适应容器重启,因此,如果 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


    【解决方案1】:

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

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

    由于没有 Rebus 处理程序将运行,当 RabbitMQ 关闭时,您将不得不处理从其他地方发送的传出消息,例如比如从网络请求发送/发布的消息。

    (...) 我希望在 RabbitMQ 关闭时发送的消息会排队等待 Rebus (...)

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

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

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

    这让您可以选择

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

    在这种情况下,为您的系统构建一些弹性的一种简单方法是使用 Polly 之类的东西尝试多次发送传出消息,以防万一失败。

    我希望这是有道理的。请让我知道是否需要详细说明。 ?


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

    【讨论】:

    • 感谢您的快速回复。我认为如果您在此处提供的信息也添加到此页面 github.com/rebus-org/Rebus/wiki/… 这可能会对其他 Rebus 用户有所帮助,重试策略仅适用于消息接收(传入消息的传递),而不是消息传递(发布到消息代理的消息)。实际上,Rebus 可以在消息代理关闭时将消息排队,但这可能是一个糟糕的设计,因为它会占用内存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多