使用EasyNetQ发布消息并断开总线时会发生什么?

时间:2015-03-05 14:53:20

标签: c# rabbitmq easynetq

我目前正在调查此事,但我想我还是要问。一旦我发现没有回答,我会发一个答案。

问题如下:

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

在处理请求时丢失与RabbitMQ的连接时会发现相同的行为。

问题是:

当总线断开连接时,EasyNetQ如何处理尝试发布消息?

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

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

还是完全抛弃了这条消息?

PublisherConfirms是否已开启影响行为?

1 个答案:

答案 0 :(得分:3)

我无法测试上述所有场景,但看起来在尝试发布到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%。还值得注意的是,总线是在我们的应用程序启动时创建的,而不是在每次调用之前创建的,因此在实际设置为有效方案之前检查标志的可能性非常低。

目前为我们工作,我们将不胜感激任何其他信息。