消息提取的确认
在未关闭消息的 ack 机制的情况下, 当消息被 Consuming 从队列中提取后, 在未明确获取确认信息之前, 队列中的消息是不会被删除的. 这样, 流程上就变成, 当消息被提取之后, 队列中的这条消息处于"等待确认"的状态. 如果 Consuming 反馈"成功"给队列, 则消息可以安全地被删除了. 如果反馈"拒绝"给队列, 则消息可能还需要再次被其它 Consuming 提取.
1 __author__ = 'li' 2 import pika 3 4 connection = pika.BlockingConnection(pika.ConnectionParameters("localhost")) 5 chanel = connection.channel() 6 chanel.queue_declare("a") 7 chanel.exchange_declare(exchange='first', exchange_type='fanout') 8 chanel.queue_bind(exchange='first', queue="a", routing_key="a") 9 for i in range(0, 10): 10 chanel.basic_publish(exchange='first', routing_key='a', body=str(i))
提取消息的逻辑:
1 # coding=utf-8 2 __author__ = 'li' 3 import pika 4 connection = pika.BlockingConnection(pika.ConnectionParameters("localhost")) 5 chanel = connection.channel() 6 for i in range(10): 7 r = chanel.basic_get(queue='a', no_ack=False) # 每次只会从消息队列中获取一条消息,并且程序执行完成后会直接退出,不在阻塞运行 8 print r[-1], r[0].delivery_tag # delivery_tag 是在 channel 中的一个消息计数, 每次消息提取行为都对应一个数字. 9 chanel.basic_ack(delivery_tag=r[0].delivery_tag, multiple=True)
要确认消息, 或者拒绝消息, 使用对应的 basic_ack 和 baskc_reject 方法:
# -*- coding: utf-8 -*-
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
r = channel.basic_get(queue='A', no_ack=False) #0
print r[-1], r[0].delivery_tag
#channel.basic_ack(delivery_tag=r[0].delivery_tag)
channel.basic_reject(delivery_tag=r[0].delivery_tag)
AMQP 协议中, 只提供了 reject 方法, 它只能处理一条消息. 因为 Consuming 是可以一次性提取多条消息的, 所以 RabbitMQ 为此做了扩展, 提供了 basic_nack 方法, 它和 basic_reject 的唯一区别就是支持一次性拒绝多条消息.
# -*- coding: utf-8 -*-
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
r = channel.basic_get(queue='A', no_ack=False) #0
r = channel.basic_get(queue='A', no_ack=False) #1
r = channel.basic_get(queue='A', no_ack=False) #2
channel.basic_nack(delivery_tag=r[0].delivery_tag, multiple=True)
delivery_tag 是在 channel 中的一个消息计数, 每次消息提取行为都对应一个数字. nack 的multiple 机制会自动把不大于指定 delivery_tag 的消息提取都 reject 掉.
在 reject 和 nack 中还有一个 requeue 参数, 表示被拒绝的消息是否可以被重新分配. 默认是True . 如果消息被 reject 之后, 不希望再被其它的 Consuming 得到, 可以把 requeue 参数设置成False :
# -*- coding: utf-8 -*-
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
r = channel.basic_get(queue='A', no_ack=False) #0
channel.basic_nack(delivery_tag=r[0].delivery_tag, multiple=False, requeue=False)
basic_consume 和 basic_get 都是从指定 queue 中提取消息, 前者是一个更高层的方法, 还支持qos 等.

浙公网安备 33010602011771号