使用RabbitMQ进行延迟消息循环

时间:2016-12-16 13:02:35

标签: rabbitmq

我正在尝试使用Rabbit的操作来实现拒绝/延迟循环,即:

我有:

  1. 使用主Exchange的主要队列绑定到它,DLX连接到StandBy Exchange。
  2. StandBy Queue与StandBy Exchange以60s TTL和DLX绑定到主交换
  3. 基本上我想:

    1. 从主要队列消费
    2. 拒绝消息(在某​​些情况下)
    3. 会因为拒绝而将其重定向到StandBy Queue
    4. 当TTL过期时,将消息重新排队到主队列。
    5. 步骤1,2和3都可以,但最后一个删除邮件而不是重新排队。

      RabbitMQ文档的一些理论我曾经设计过这个:

        

      来自队列的消息可以是“死信”;也就是说,当发生以下任何事件时,重新发布到另一个交易所:

           
          
      1. 使用requeue = false,
      2. 拒绝邮件(basic.reject或basic.nack)   
      3. 邮件的TTL过期;或
      4.   
      5. 超出了队列长度限制。
      6.         

        ...

             

        可以形成消息死字的循环。例如,当队列在没有指定死信路由密钥的情况下将消息写入默认交换时,就会发生这种情况。如果在整个周期中没有拒绝,那么这些周期中的消息(即两次到达同一队列的消息)将被丢弃。

      该理论说它应该重新排队,因为它在步骤#2的循环中有一个拒绝,所以,你能帮我弄清楚为什么它会丢弃消息而不是重新排序是吗?

      更新

      我定位的版本是2.8.4,似乎在那一刻if there was no rejections in the entire cycle不在用例中,无论如何你可以自己查看RabbitMQ 2.8.x Docs

      我会接受@george回答,因为这段代码可以实现原始目标。

1 个答案:

答案 0 :(得分:1)

Rafael,我不确定您使用的是哪个客户端,但使用Python中的Pika客户端,您可以实现类似的功能。为简单起见,我只使用一次交换。您确定要正确设置交换机和路由密钥吗?

sender.py

import sys
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
               'localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='cycle', type='direct')
channel.queue_declare(queue='standby_queue',
                      arguments={
                          'x-message-ttl': 10000,
                          'x-dead-letter-exchange': 'cycle',
                          'x-dead-letter-routing-key': 'main_queue'})
channel.queue_declare(queue='main_queue',
                      arguments={
                          'x-dead-letter-exchange': 'cycle',
                          'x-dead-letter-routing-key': 'standby_queue'})
channel.queue_bind(queue='main_queue', exchange='cycle')
channel.queue_bind(queue='standby_queue', exchange='cycle')
channel.basic_publish(exchange='cycle',
                      routing_key='main_queue',
                      body="message body")
connection.close()

receiver.py

import sys
import pika
def callback(ch, method, properties, body):
    print "Processing message: {}".format(body)
    # replace with condition for rejection
    if True:
        print "Rejecting message"
        ch.basic_nack(method.delivery_tag, False, False)
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.basic_consume(callback, queue='main_queue')
channel.start_consuming()