RabbitMQ - 处理不可靠的服务

RabbitMQ - deal with unreliable service

我有一个 AAA 服务,它每分钟向 RabbitMQ 交换器发送 10 到 50,000 条消息。 .NET Core 服务 BBB 订阅一个队列(所有消息都路由到该队列),并针对每条消息通过 Internet 调用另一个 HTTP 服务 CCC。问题是 CCC 非常不可靠,一天几次它会完全关闭一两分钟,至少每周一次它会死一个小时。

我无法控制 AAA 或 CCC。我如何使用 RabbitMQ 路由功能可靠地传递所有消息?

假设你在AAA中的订阅方法是同步的,抛出异常会导致Rabbit将消息放入死信queue。从那里您可以将它们移回或手动检查它们。或者,您可以 re-publish 它到同一个交换,但是您可能会遇到故障转移和填充 queue 的消息的问题。为避免这种情况,请使用 header 发布它,以防止它再次进入原始 queue。创建另一个使用新 header 作为过滤器的持久性 queue。 Presto,你有一个 re-try queue。您可以订阅它以获取重试 and/or 警报,使用 Shovel 将消息移回原始 queue,等等。

对于离线几分钟或几小时的不可靠的第三方服务 CCC,circuit-breaker 可能很有用。配置断路器在检测到 CCC 离线时断开。

您可以监控断路器状态以检测 CCC 何时离线and/or记录电路状态的变化以供日后分析。

Polly 的断路器允许您hook in any custom code on transitions of circuit state,因此您还可以:

  • 断路时,退订RabbitMQ队列
  • 当电路半开时,以窄并行度重新订阅 RabbitMQ 队列(例如,预取计数仅为 1 或 2 ...只有足够的消息让断路器重试电路) .
  • 当电路关闭(再次健康)时,以全吞吐量重新订阅 RabbitMQ 队列。

一旦断路器检测到 CCC 离线,此模式将阻止您让 100000 条消息流向 RabbitMQ error/dead-letter/your 自定义重试队列。

您仍然需要考虑失败的消息会发生什么情况(在断路之前或重新测试时),如 中所述。将他们引导至 error/retry 队列。或者,如果 unsubscribe-when-CCC-is-down 模式与您的现实世界参数配合得很好,您可以让简单地 return 失败的消息进入原始队列。


如果 CCC 也遇到任何 瞬态 故障(故障仅持续几秒钟),请考虑引入 WaitAndRetry policy


传入消息速率可能为每秒 1000 秒,您可能需要考虑如何限制 BBB 内消息处理的 并行性 and/or 您设置的超时呼叫 CCC。如果没有这个,你可能 risk memory bulges in the consumer 随着越来越多的消息到达,而其他请求在 CCC 超时之前挂起响应; CCC 上的高超时显然加剧了这一点。可以通过使用手动 ack 并应用 pre-fetch count.

来限制消费者并行性