我的Unacked比工人多可能怎么样?

时间:2016-03-04 17:38:40

标签: rabbitmq bunny

我有一个有1名工人的队列。 impl。看起来像那样:

def work
    connection = get_connection
    connection.start
    channel = connection.create_channel
    queue   = channel.queue("crawl", :durable => true)

    multi_log " [*] Worker waiting for messages in #{queue.name}. To exit press CTRL+C"

    begin
      queue.subscribe(:ack => true, :block => true) do |delivery_info, properties, message|
        multi_log " [x] Worker received #{message}"
        process_work message
        channel.ack(delivery_info.delivery_tag)
        multi_log " [x] Worker job done for #{message}"
      end
    rescue => e
      log.error e.message
      log.error e.backtrace.join("\n")
      connection.close
    end
  end

只要执行作业,消费者就会阻止。根据我的理解,这个消费者一次只能处理1份工作。但令我困惑的是,在RabbitMQ管理UI中,我看到有时候2或3个Unacked用于该队列。但那怎么可能呢?

2 个答案:

答案 0 :(得分:0)

解决方案的发布方面正在填补队列(间接通过交换 - 无法说明,因为您没有提供详细信息)。订阅者(工作者)的数量与未包装的消息数量无关。在您的情况下,似乎很简单:发布商比订阅者更快。

答案 1 :(得分:0)

昨天晚上我发现了:)问题是预取没有明确设置。如果您设置channel.prefetch(1),则消费者将一次只收到1条消息。如果未设置预取值,则消费者会尽可能多地接收消息。所以完整的代码现在看起来像那样。

  def work
    connection = get_connection
    connection.start
    channel = connection.create_channel
    channel.prefetch(1)
    queue   = channel.queue("crawl", :durable => true)

    multi_log " [*] Worker waiting for messages in #{queue.name}. To exit press CTRL+C"

    begin
      queue.subscribe(:ack => true, :block => true) do |delivery_info, properties, message|
        multi_log " [x] Worker received #{message}"
        process_work message
        channel.ack(delivery_info.delivery_tag)
        multi_log " [x] Worker job done for #{message}"
      end
    rescue => e
      log.error e.message
      log.error e.backtrace.join("\n")
      connection.close
    end
  end

现在,RabbitMQ管理界面显示,例如,有9条消息准备就绪,1条未分组,总共10条。这就像预期的那样。

顺便说一句,在Java中,您可以像这样channel.basicQos(1);设置预取。