代码之家  ›  专栏  ›  技术社区  ›  Géry Ogam

rabbitmq请求顺序

  •  0
  • Géry Ogam  · 技术社区  · 7 年前

    根据Rabbitmq文档 Consumer Acknowledgements :

    当消息被重新排队时,如果可能的话,它将被放在队列中的原始位置。如果不是(由于多个消费者共享一个队列时来自其他消费者的并发传递和确认),则消息将重新排队到靠近队列头的位置。

    如果服务器队列最初是

    尾部[C B A]头部

    客户机使用者使用头消息(“A”),服务器队列应该变成:

    尾部[Cb]头

    然后,如果客户机使用者捕获处理过的消息,则消息应在头部的服务器队列中重新排队(根据文档,它的“原始位置”),服务器队列应变为:

    尾部[C B A]头部

    最后,客户机使用者应该再次使用相同的头消息(“A”)。

    但这不是我使用python库pika观察到的。我观察到,nacked消息在服务器队列的尾部而不是在头部(原始位置)重新排队。rabbitmq文档正确还是库PIKA正确?

    样例代码:

    import logging
    
    import pika
    
    logging.basicConfig(level=logging.INFO)
    logging.getLogger("pika").propagate = False
    parameters = pika.ConnectionParameters()
    
    
    # Produce messages
    
    with pika.BlockingConnection(parameters) as connection:
        queue = "foobar"
        routing_key = queue
        channel = connection.channel()
        channel.queue_declare(queue=queue)
    
        for body in ["a", "b", "c"]:
            channel.publish(exchange="", routing_key=routing_key, body=body)
            logging.info("Produced message %r with routing key %r", body, routing_key)
    
    
    # Consume messages
    
    def handle(channel, method, properties, body):
        logging.info("Consumed message %r from queue %r", body.decode(), queue)
        channel.basic_nack(method.delivery_tag)
    
    
    with pika.BlockingConnection(parameters) as connection:
        queue = "foobar"
        channel = connection.channel()
        channel.queue_declare(queue=queue)
        channel.basic_consume(queue=queue, on_message_callback=handle)
        channel.start_consuming()
    

    输出:

    信息:根:生成了带有路由键“foobar”的消息“a”
    信息:根:生成了带有路由键“foobar”的消息“b”
    信息:根:生成了带有路由键“foobar”的消息“c”
    信息:根:已使用队列“foobar”中的消息“a”
    信息:根:已使用队列“foobar”中的消息“b”
    信息:根:已使用队列“foobar”中的消息“c”
    信息:根:已使用队列“foobar”中的消息“a”
    信息:根:已使用队列“foobar”中的消息“b”
    信息:根:已使用队列“foobar”中的消息“c”
    信息:根:已使用队列“foobar”中的消息“a”
    信息:根:已使用队列“foobar”中的消息“b”
    信息:根:已使用队列“foobar”中的消息“c”

    2 回复  |  直到 7 年前
        1
  •  1
  •   Olivier    7 年前

    您遇到的行为很可能是由于预取行为。

    由于您没有具体说明所需的服务质量,我相信(如果您能提供一个知识更丰富的信息来源来确认这一点,我会很感激吗?)预取由服务器决定,可能会非常高。

    其思想是,对于性能问题,客户机可以获得多条消息,这在大多数情况下都是有利的:

    • 如果用户端有多线程,那么他可能能够并行处理多个消息,因此在给定的时间内有多个消息尚未打包。
    • 为了在“快乐”的情况下进行更流畅的处理,客户机可以对一个消息块进行ACK,让服务器知道,在给定的消息之前,客户机接收到的所有消息都是ACK,当我们有大量需要很少处理的消息的情况时,它减少了开销。

    如果检查下面的文档链接,它们将解释如何控制行为。

    有关这些点的其他信息,请访问:

        2
  •  0
  •   Géry Ogam    7 年前

    谢谢你@olivier。用 channel.basic_qos(prefetch_count=1) 我得到记录在案的行为:

    信息:根:生成了带有路由键“foobar”的消息“a”
    信息:根:生成了带有路由键“foobar”的消息“b”
    信息:根:生成了带有路由键“foobar”的消息“c”
    信息:根:已使用队列“foobar”中的消息“a”
    信息:根:已使用队列“foobar”中的消息“a”
    信息:根:已使用队列“foobar”中的消息“a”
    信息:根:已使用队列“foobar”中的消息“a”
    信息:根:已使用队列“foobar”中的消息“a”
    信息:根:已使用队列“foobar”中的消息“a”
    信息:根:已使用队列“foobar”中的消息“a”
    信息:根:已使用队列“foobar”中的消息“a”
    信息:根:已使用队列“foobar”中的消息“a”