RabbitMQ / Pika - 保证在创建的订单中收到消息?

时间:2012-05-14 15:48:20

标签: python messaging rabbitmq amqp pika

举个简单的例子,我在新的RabbitMQ(v 2.6.1)队列中添加了5个项目:

import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(host='not.my.real.server.net'))
channel = connection.channel()
channel.queue_declare(queue='dw.neil',durable=True)
# add 5 messages to the queue, the numbers 1-5
for x in range(5):
    message = x+1
    channel.basic_publish(exchange='',routing_key='dw.neil', body=str(message))
    print " [x] Sent '%s'" % message
connection.close()

我清除队列,然后运行上面的代码添加5个项目:

nkodner@hadoop4 sports_load_v2$ python send_5.py 
 [x] Sent '1'
 [x] Sent '2'
 [x] Sent '3'
 [x] Sent '4'
 [x] Sent '5'

现在,我正在尝试模拟失败的处理。给出以下代码从队列中消耗。请注意,我已将对basic_ack的调用注释掉:

#!/usr/bin/env python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(host='not.my.real.server.net'))
channel = connection.channel()
channel.queue_declare(queue='dw.neil',durable=True)
method_frame, header_frame, body=channel.basic_get(queue='dw.neil')
print method_frame, header_frame
print "body: %s" % body
#channel.basic_ack(delivery_tag=method_frame.delivery_tag)
connection.close()

我运行接收代码以从队列中取出一个项目。正如我所料,我得到了第1项:

nkodner@hadoop4 sports_load_v2$ python r5.py 
<Basic.GetOk(['message_count=9', 'redelivered=False', 'routing_key=dw.neil', 'delivery_tag=1', 'exchange='])>
<BasicProperties([])>
body: 1

由于对channel.basic_ack()的调用已被注释掉,我希望将未确认的消息放在队列中,以便下一个消费者获得它。我希望消息#1是队列中的第一条消息(再次),Redelivered属性设置为True。而是收到消息#2:

nkodner@hadoop4 sports_load_v2$ python r5.py 
<Basic.GetOk(['message_count=9', 'redelivered=False', 'routing_key=dw.neil', 'delivery_tag=1', 'exchange='])>
<BasicProperties([])>
body: 2

队列中的所有其他消息都会在#1返回之前收到,并且Redelivered标志设置为True:

...

nkodner@hadoop4 sports_load_v2$ python r5.py 
<Basic.GetOk(['message_count=9', 'redelivered=False', 'routing_key=dw.neil', 'delivery_tag=1', 'exchange='])>
<BasicProperties([])>
body: 5

nkodner@hadoop4 sports_load_v2$ python r5.py 
<Basic.GetOk(['message_count=9', 'redelivered=True', 'routing_key=dw.neil', 'delivery_tag=1', 'exchange='])>
<BasicProperties([])>
body: 1

我可以设置任何属性或选项,以便在确认之前一直交付#1吗?

我的用例是使用顺序生成的文件加载数据仓库。我们正在使用基于消息的处理让我的程序知道一些新文件已准备就绪并将被加载到DW中。我们必须按照生成的顺序处理文件。

2 个答案:

答案 0 :(得分:3)

RabbitMQ 2.7.0已经解决了这个问题 - 我们运行的是2.6.1。

来自release notes

  

此版本中的新功能包括:

     
      
  • 保留为消费者重新排队的邮件
  •   

答案 1 :(得分:1)

尝试使用channel.basic_reject - 这应该将未确认的消息推送回RabbitMQ,RabbitMQ会将消息视为新消息。此外 - 如果您遇到失败的消息,您可以使用channel.basic_recover告诉RabbitMQ重新传递所有未确认的消息。

http://www.rabbitmq.com/extensions.html#negative-acknowledgements提供有关Basic.Reject与Basic.Nack的区别信息。

消息排序语义在http://www.rabbitmq.com/semantics.html

中解释