我有一个有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用于该队列。但那怎么可能呢?
答案 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);
设置预取。