我有一个服务 AAA,每分钟向 RabbitMQ 交换发布 10 到 5 万条消息。一个 .NET Core 服务 BBB 订阅一个队列(所有消息都被路由到该队列),并为每条消息通过 Internet 调用另一个 HTTP 服务 CCC。问题是 CCC 非常不可靠,一天几次它会完全关闭一两分钟,每周至少一次它会死掉一个小时。
我无法控制 AAA 或 CCC。如何使用 RabbitMQ 路由功能可靠地传递所有已处理的消息?
我有一个服务 AAA,每分钟向 RabbitMQ 交换发布 10 到 5 万条消息。一个 .NET Core 服务 BBB 订阅一个队列(所有消息都被路由到该队列),并为每条消息通过 Internet 调用另一个 HTTP 服务 CCC。问题是 CCC 非常不可靠,一天几次它会完全关闭一两分钟,每周至少一次它会死掉一个小时。
我无法控制 AAA 或 CCC。如何使用 RabbitMQ 路由功能可靠地传递所有已处理的消息?
对于离线数分钟或数小时的不可靠第三方服务 CCC,断路器可能很有用。将断路器配置为在检测到 CCC 离线时断开。
您可以监视断路器状态以检测 CCC 何时离线和/或记录电路状态的变化以供以后分析。
Polly 的断路器允许您在电路状态转换时挂接任何自定义代码,因此您还可以:
一旦断路器检测到 CCC 离线,此模式将阻止您获得 100000 条消息流向 RabbitMQ 错误/死信/您的自定义重试队列。
如另一个答案中所述,您仍然需要考虑确实失败的消息会发生什么(在断路之前或重新测试时)。将它们定向到错误/重试队列。或者,如果 unsubscribe-when-CCC-is-down 模式与您的真实世界参数配合得很好,您可以让失败的消息简单地返回到原始队列。
如果 CCC 也遇到任何瞬时故障(故障仅几秒钟),请考虑引入WaitAndRetry 策略。
由于传入消息的速率可能为每秒 1000 秒,您可能需要考虑如何限制BBB 中消息处理的并行性和/或在调用 CCC 时设置的超时。如果没有这个,你可能会冒着消费者内存膨胀的风险,因为越来越多的消息到达,而其他请求在超时之前挂在来自 CCC 的响应上;CCC 的高超时显然加剧了这一点。消费者并行性可以通过使用手动ack
和应用pre-fetch count
.
假设你在 AAA 中的订阅方式是同步的,抛出异常会导致 Rabbit 将消息放入死信队列。从那里您可以将它们移回或手动检查它们。或者,您可以将其重新发布到同一个交换器,但您可能会遇到故障转移和过度填满队列的消息的问题。为避免这种情况,请使用标题发布它,以防止它再次进入原始队列。创建另一个使用新标头作为过滤器的持久队列。Presto,你有一个重试队列。您可以订阅它以进行重试和/或警报,使用 Shovel 将消息移回原始队列,等等。