【问题标题】:How to gracefully disconnect from rabbitmq queue如何优雅地与rabbitmq队列断开连接
【发布时间】:2018-02-09 08:48:32
【问题描述】:

我的 rabbitmq 客户端遇到了赛车状况问题。我的服务有多个实例侦听单个队列,将接收到的消息存储到数据库中。

当它们同时重新启动时,我有时会看到消息被重新传递并存储在数据库中两次。这通常在客户端通过检查相关 ID 是否已存储在数据库中来处理。这在 99.9% 的时间里都有效(我每天处理 5 条消息,每天发生一到两次)。

正如我所说,我怀疑是赛车状况造成的。我想我的第一条消息仍在处理中时再次收到消息。所以当我检查时我没有看到它存储在数据库中,最后存储了两次。

我不应该认为这不是问题,而是一直困扰着我,因为我无法真正解释发生了什么。

我怀疑它在我重新启动服务时发生。我想我与队列断开连接,而我仍在处理消息,触发 rabbitmq 再次重新传递到另一个尚未关闭的实例。

我想要做的是当我停止服务时

  • 告诉rabbitmq我不想再收到消息了
  • 等待所有当前正在处理的消息完成
  • 发送ack / nacks
  • 关机

现在我首先注销收到的事件

_consumerServer.Received -= MessageReceived;

然后我正在处理频道和服务器

        if (_channel != null)
        {
            _channel.Close();
            _channel.Dispose();
        }

        if (_connectionServer != null)
        {
            _connectionServer.Close();
            _connectionServer.Dispose();
        }

【问题讨论】:

  • 使用像 ZooKeeper 这样的分布式锁系统怎么样?
  • 我对ZooKeeper不熟悉,但我会看看
  • 我认为你必须手动实现,通过使用一些线程同步结构(如Monitor.Wait\Pulse)来确保MessageReceived 中的所有处理在关闭之前完成。或者只是不允许向数据库插入重复项(通过唯一索引或通过仔细的 sql 查询)。

标签: c# rabbitmq windows-services


【解决方案1】:

RabbitMQ 团队会监控 this mailing list,并且有时只会在 StackOverflow 上回答问题。


您应该正确处理重新传递,而不是尝试关闭消费者以便不再重新传递消息。检查并处理在消息上设置了redelivered 标志的情况,并采取适当的行动。您还应该尝试以存储操作是幂等的方式存储消息 - 即它可以发生多次,并且您的数据库中只有一条记录。

请在此处查看团队提供的指南:

https://www.rabbitmq.com/reliability.html#consumer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    • 2015-06-25
    • 1970-01-01
    • 2014-10-19
    相关资源
    最近更新 更多