消息提取的确认

在未关闭消息的 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 等.

posted @ 2015-09-07 21:14  程序猿进化之路  阅读(620)  评论(0)    收藏  举报