Python 当预回迁计数=1时,拒绝并重新为RabbitMQ任务添加资源

Python 当预回迁计数=1时,拒绝并重新为RabbitMQ任务添加资源,python,rabbitmq,pika,Python,Rabbitmq,Pika,假设我有一个包含五项的队列: (tail) E, D, C, B, A (head) 我使用来自此队列头的消息,但确定当前不适合处理消息A。I拒绝具有requeue=True的项目,队列变为: (tail) A, E, D, C, B (head) 然后,我使用B、C、D、和E、ack对每一个进行编码。现在,队列中只有A,我不断地使用它,并在一个永无止境的循环中一次又一次地拒绝它。如果一条新的、非的消息进入,它几乎会立即被消费,然后流程会继续尝试消费一条的循环 我对Pika文档中的 impo

假设我有一个包含五项的队列:

(tail) E, D, C, B, A (head)
我使用来自此队列头的消息,但确定当前不适合处理消息
A
。I
拒绝
具有
requeue=True
的项目,队列变为:

(tail) A, E, D, C, B (head)
然后,我使用
B
C
D
、和
E
ack
对每一个进行编码。现在,队列中只有
A
,我不断地使用它,并在一个永无止境的循环中一次又一次地拒绝它。如果一条新的、非
消息进入,它几乎会立即被消费,然后流程会继续尝试消费
一条
的循环

我对Pika文档中的

import pika
from pika import exceptions
from pika.adapters import twisted_connection
from twisted.internet import defer, reactor, protocol,task


@defer.inlineCallbacks
def run(connection):

    channel = yield connection.channel()

    exchange = yield channel.exchange_declare(exchange='topic_link',type='topic')

    queue = yield channel.queue_declare(queue='hello', auto_delete=False, exclusive=False)

    yield channel.queue_bind(exchange='topic_link',queue='hello',routing_key='hello.world')

    #yield channel.basic_qos(prefetch_count=1)

    queue_object, consumer_tag = yield channel.basic_consume(queue='hello',no_ack=False)

    l = task.LoopingCall(read, queue_object)

    l.start(0.01)


@defer.inlineCallbacks
def read(queue_object):

    ch,method,properties,body = yield queue_object.get()

    print body

    if body == 'A':
        yield ch.basic_reject(delivery_tag=method.delivery_tag, requeue=True)
    else:
        yield ch.basic_ack(delivery_tag=method.delivery_tag)


parameters = pika.ConnectionParameters()
cc = protocol.ClientCreator(reactor, twisted_connection.TwistedProtocolConnection, parameters)
d = cc.connectTCP('hostname', 5672)
d.addCallback(lambda protocol: protocol.ready)
d.addCallback(run)
reactor.run()
问题:注意以下注释行:

#yield channel.basic_qos(prefetch_count=1)
当我取消注释时,消费者到达消息
A
,它将在
拒绝它之后立即再次拾取它,忽略它后面队列中可能等待的任何其他项目。它没有将被拒绝的项目放在队列的尾部,而是不断地重复尝试,完全阻塞队列中的所有其他内容

注释掉该行后,它工作正常(尽管速度稍慢)。如果该行存在并且
预回迁计数>1
,它也可以工作。将其精确设置为
1
会触发此行为


在拒绝邮件
a
时,我是否缺少一个步骤?或者Pika的预取系统从根本上与此edge案例不兼容?

如果您只有一个消费者,那么RabbitMQ除了将消息发送给被拒绝的同一消费者之外别无选择(无论是使用basic.reject还是basic.nack)

当您设置
prefetch\u count>1
时,您的消费者将收到您的循环消息,以及来自循环消息旁边头部的新消息(实际上,您的循环消息将保留在头部)


如果您意外地得到
N*M
带有
prefetch\u计数的循环消息,假设我不介意通过重复循环相同的消息来消耗CPU时间。是否有一种方法可以完全拒绝预回迁队列中的消息,以便在循环返回之前,它后面的任何有效消息都可以通过?您可以完全删除无效消息,并可能将其放入其他队列中,以便稍后手动或以其他方式处理它,但这取决于消息流的活动程度。