【问题标题】:Having no error when acking message failed确认消息失败时没有错误
【发布时间】:2019-05-29 23:20:33
【问题描述】:

有时,大约 10000 个兔子应答中的 1 个我无法正确应答。

在我确认message A 时失败的情况下,我也没有例外。似乎一切都很顺利。当我进入下一个message B 时,我得到了异常System.IO.EndOfStreamException: SharedQueue。堆栈跟踪表明在 RabbitMQ.Util.SharedQueue.EnsureIsOpen() 中引发了异常,这是私有方法。

有一个问题 - A message 未被确认!我ack的时候也没有异常,但是还是没有ack!两个应用程序获得相同消息的可能性很小。有什么我可以做的吗?

我已经尝试更改一些设置,例如:

AutomaticRecoveryEnabled = true;
RequestedHeartbeat = 60;
NetworkRecoveryInterval = TimeSpan.FromSeconds(10);

并在每次确认之前编写了一个测试连接的方法:

public bool HasFullConnection() {
    if (!HasServerConnection(Config.ConnectionConfig.HostAddress)) return false;
    if (!RabbitMQConnection.IsOpen) return false;
    if (!RabbitMQClient.IsOpen) return false;

    return true;
}

不幸的是 - 问题仍然存在。

【问题讨论】:

  • 让我们知道您经纪人的日志文件中的内容非常有帮助。

标签: c# rabbitmq


【解决方案1】:

所以,这里发生了几件事。首先,您现在可能已经发现,C# 客户端库不能很好地处理非标称情况。其次,更重要的是,您的应用程序设计要求在acking 上具有 100% 的可靠性,而它不应该这样做。

万分之一(或 0.01%)的故障率相当不错。如果您仅在 0.01% 的消息中看到 ack 失败,我认为这是可以接受的失败级别。 RabbitMQ 中的确认是异步传递给代理的,并且基于最初接收消息的通道和消费者。在收到消息和实际确认消息之间可能会发生许多事情。因此,如果发生任何中断消费者、通道、代理或连接的事情,则假定消息已失败并重新传递。

这被称为至少一次交付。对此的替代方案是最多一次交付(替代方案不使用确认)。因此,假设您最多使用一次传递,您的系统应设计为处理重新传递的消息。

【讨论】:

  • 如果它认为它已成功确认,我将无法重新发送消息。有没有办法检查与兔子的连接是否仍然存在? RabbitMQ.Util.SharedQueue.EnsureIsOpen() 似乎是一种方法,但由于某种原因,这种方法是私有的。我需要一种同步方法来检查连接状态。这可能会限制我的 acking 问题。我可以检查连接是否正常,然后完成工作。我最多 5 条消息/秒,所以这不会造成很大的性能损失。
  • 不,从您的评论看来,您有一个相当严重的设计问题。您能否提供更多详细信息或解释为什么重复消息是世界末日?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-28
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 2013-01-15
  • 1970-01-01
相关资源
最近更新 更多