c# - 当使用 EasyNetQ 发布消息并且总线断开连接时会发生什么?

标签 c# rabbitmq easynetq

我目前正在调查此问题,但我还是想问问。如果没有回答,我会在发现后发布答案。

问题如下:

应用程序调用 RabbitHutch.CreateBus 来创建 IBus/IAdvancedBus 的实例,以将消息发布到 RabbitMQ。返回实例,但 IsConnected 标志设置为 false(即连接重试在后台完成)。当应用程序为特定请求提供服务时,调用 IAdvancedBus.PublishAsync 以在总线仍未连接时发布消息。在负载很大的情况下,对应用程序的请求最终会超时,因为总线永远无法连接到 RabbitMQ。

在处理请求时与 RabbitMQ 的连接丢失时会观察到相同的行为。

问题是:

EasyNetQ 如何处理总线断开时发布消息的尝试?

在建立连接之前,消息是否在内存中排队?如果是这样,它是否会在达到某个限制后处理消息?这是可配置的吗?

还是强制总线尝试连接到 RabbitMQ?

还是完全转储消息?

PublisherConfirms 是否打开影响行为?

最佳答案

我无法测试上述所有场景,但看起来在尝试发布到 RabbitMQ 之前,EasyNetQ 正在检查总线是否已连接。如果不是,它或多或少会进入连接循环,如下所述:https://github.com/EasyNetQ/EasyNetQ/wiki/Error-Conditions#there-is-a-network-failure-between-my-subscriber-and-the-rabbitmq-broker

随着负载的增加,连接循环似乎正在失控,因为我们的基础设施或配置已损坏,因此没有一个能够连接到 RabbitMQ。为什么我们会超时我还没有确定,但我怀疑当多个连接循环尝试同时连接时可能会出现并发问题。

我也怀疑关闭 PublisherConfirms 是否有帮助,因为我们无法发布消息,因此不等待 RabbitMQ 的确认。

我们的解决方案:

那么为什么我没有得到这个问题的明确答案呢?事实是,严格来说,目前我们试图发布的消息并不是关键任务。如果我们的配置有误,运行健康检查时部署将失败,我们基本上会中止部署。如果 RabbitMQ 由于某种原因变得不可用,我们可以不发布这些消息。

此外,为避免超时,我们将使用断路器结束消息发布,以在我们检测到应用程序与 RabbitMQ 之间的电路打开时停止消息发布。粗略地说,它的工作原理如下:

var bus = RabbitHutch.Create(...).Advanced;
var rabbitMqCircuitBreaker = new CircuitBreaker(...);
rabbitMqCircuitBreaker.AttemptCall(() => {
    if (!bus.IsConnected)
       throw new Exception(...);
    bus.Publish(...);
});

请注意,当 IsConnected 标志设置为 false 时,我们通过抛出异常来通知我们的断路器存在问题。如果在配置的时间段内异常被抛出 X 次,电路将打开,我们将停止尝试在配置的时间内发布消息。我们认为这是可以接受的,因为如果 RabbitMQ 可用,连接应该非常快并且 99.xxx% 的时间都可用。另外值得注意的是,总线是在我们的应用程序启动时创建的,而不是在每次调用之前创建的,因此在有效场景中实际设置标志之前检查标志的可能性非常低。

目前为我们工作,如有任何额外信息,我们将不胜感激。

关于c# - 当使用 EasyNetQ 发布消息并且总线断开连接时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28880775/

相关文章:

c# - 如何检测图像中的不规则边界?

c# - Xamarin 工作簿 : Use of namespaces

java - RabbitMQ 同一队列的多个消费者

go - RabbitMQ: d.Ack() 关闭 channel

c# - 无法在 Unity 项目上添加 EasyNetQ 的引用

c# - 将数组传递给可变长度参数列表

C# - DatagridView 和上下文菜单

java - 在 rabbitmq 中配置优先级

asp.net-core - 如何为 ASP.NET Core 服务提供者编写 EasyNetQ 自动订阅者调度程序?

architecture - 已发布并等待对 RabbitMQ/EasyNetQ 主题的回应 - 如何只获得你的?