描述
python在rabbitmq中的确认机制可以保证rabbitmq消费者连接断了,消息不丢失,在连接重新建立的时候,在重发那些没有接收到的消息.
rabbitmq支持一种方式:应答。比如我从消息里拿一条消息,如果全处理完,你就不要帮我记着了。如果没处理完,突然断开了,再连接上的时候,消息队列就会重新发消息。
总结:
- Basic.Ack 发回给 RabbitMQ 以告知,可以将相应 message 从 RabbitMQ 的消息缓存中移除。
- Basic.Ack 未被 consumer 发回给 RabbitMQ 前出现了异常,RabbitMQ 发现与该 consumer
对应的连接被断开,之后将该 message 以轮询方式发送给其他 consumer (假设存在多个 consumer 订阅同一个
queue)。 - 在 no_ack=true 的情况下,RabbitMQ 认为 message 一旦被 deliver出去了,就已被确认了,所以会立即将缓存中的 message 删除。所以在 consumer 异常时会导致消息丢失。
- 来自 consumer 侧的 Basic.Ack 与 发送给 Producer 侧的 Basic.Ack 没有直接关系
注意:
1)只有在Consumer(消费者)断开连接时,RabbitMQ才会重新发送未经确认的消息。
2)超时的情况并未考虑:无论Consumer需要处理多长时间,RabbitMQ都不会重发消息。
关键代码
- 在接收端的callback最后:
channel.basic_ack(delivery_tag=method.delivery_tag)
2)除了callback函数,还要在之前设置接收消息时指定no_ack(默认False)或auto_ack=False:
channel.basic_consume(callback, queue=‘ack_test’, auto_ack=False)
import pika
# ########################### 消费者 ##########################
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='127.0.0.1'))
channel = connection.channel()
channel.queue_declare(queue='ack_test')
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
print('success!')
ch.basic_ack(delivery_tag = method.delivery_tag) # 关键代码一
channel.basic_consume(callback,
queue='ack_test',
no_ack=False) # 关键代码二
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
只需要修改消费者的代码即可.
最终效果是:消费者断掉连接,再次连接,消息还会收到。