为什么RabbitMQ队列所有消息启动消费者后全部变为未确认状态?
问题原因
这是RabbitMQ默认预取策略导致的正常现象:当消费者auto_ack设为False时,RabbitMQ默认的prefetch_count参数值为0,代表无限制预取,Broker会直接把队列中所有可消费的消息一次性推送给连接的消费者,所有消息都会进入未确认状态,等待消费者返回ACK。
你的消费者每次处理消息需要休眠1秒,处理速度远低于消息推送速度,所以启动后会立刻将队列中几乎所有消息都拉到本地待处理,表现为messages_ready归零,messages_unacknowledged接近原队列总消息数。
解决方法
在调用basic_consume之前,添加QoS(服务质量)配置,限制单消费者同时持有未确认消息的最大数量即可:
def scan_from_mq(server: str, port: int, queue_name: str) -> None: connection = pika.BlockingConnection(pika.ConnectionParameters(host=server, port=port)) channel = connection.channel() channel.queue_declare(queue=queue_name) # 新增这行配置,限制每次最多预取1条未确认的消息 channel.basic_qos(prefetch_count=1) def callback(ch, method, properties, body): print(body) time.sleep(1) ch.basic_ack(delivery_tag=method.delivery_tag) channel.basic_consume(queue='generated_buckets', on_message_callback=callback, auto_ack=False) print(' [*] 等待消息,按Ctrl+C退出') channel.start_consuming()
配置后RabbitMQ只会在消费者返回上一条消息的ACK后,才会推送下一条消息,不会再出现全队列消息都变成未确认的情况。
补充说明
- 可以根据消费逻辑的处理速度调整
prefetch_count的数值,如果消费耗时极短,可以设为5~10,平衡预取开销和消费吞吐量 - 如果有多个消费者消费同一个队列,该配置可以实现均匀的负载均衡,避免单个消费者被大量未确认消息占满
内容的提问来源于stack exchange,提问作者Dan S
相关产品推荐
相关产品推荐

