从RabbitMQ获取消息而不消耗

时间:2019-02-25 13:09:20

标签: python-3.x rabbitmq

我想获取Rabbitmq队列中存在的消息的副本而不消耗它们。可能吗 ? 预先感谢,

3 个答案:

答案 0 :(得分:1)

  

我想获取Rabbitmq队列中存在的消息的副本   不消耗它们。有可能吗?

不。您最接近的选择是消费或获取消息,然后通过否定确认拒绝它。


注意: RabbitMQ团队监视rabbitmq-users mailing list,并且有时仅在StackOverflow上回答问题。

答案 1 :(得分:0)

也许您可以注册消费者(如官方文档中的here所示)而无需给予经纪人确认no_ack=True

channel.basic_consume(callback, queue='hello', no_ack=True)

通过这种方式,您的使用者可以接收消息内容,但是消息本身没有被代理标记为已发送(当使用者退出时返回Ready状态)。

也许这不是做您所需的最干净的方法,但是它有效并且很简单。

您可以采用的另一种(但类似)方法基于所谓的 pull API (与注册时使用的 push API 相反)订户);我在.Net应用程序中使用了这种方法:您可以找到.Net文档here,并且我认为Python API也是如此。

关键思想是在不加确认的情况下获得消息:channel.BasicGet(queueName, noAck)

我希望这可以帮助您迈向完整而可靠的解决方案!

答案 2 :(得分:0)

我发现有一种更好的方法,可以使用channel.basic_get()函数将所有消息发送到队列中,如以下代码所示:

    def __init__(self):
        self.host = ConfigTools().get_attr('host')
        self.waiting_queue = ConfigTools().get_attr('test_queue_name')

    def view_queue(self) -> list:
        """Reads everything from the queue, then disconnects, causing the server to requeue the messages
        Returning the delivery tag is pointless at this point because the server makes the tag (an integer) up on
        the fly and the order can shuffle constantly"""
        connection = pika.BlockingConnection(
            pika.ConnectionParameters(host=self.host))

        msgs = []
        while True:
            chl = connection.channel()
            method_frame, header_frame, body = chl.basic_get(queue='test')
            if method_frame:
                print("body : ", body)
                msgs.append(body)
            else:
                print("No more messages returned")
                connection.close()
                break
        return msgs

然后,如果任何时候我知道要弹出队列中的哪一条消息,我都可以使用类似的内容:

    def remove(self, item) -> list:
        """Removes the item from the queue. Goes through the entire queue, similar to view_queue, and acknowledges
        the msg in the list that matches, and returns the msg.
        If item matches more than one message on the queue, only one is deleted
        """

        if isinstance(item, list):
            if not (isinstance(i, bytes) for i in item):
                print("Item must be a list of only byte objects")
        if not isinstance(item, bytes):
            print("Item must be a singe bytes object")
            raise TypeError

        connection = pika.BlockingConnection(
            pika.ConnectionParameters(host=self.host))

        msgs = []
        while True:
            chl = connection.channel()
            method_frame, header_frame, body = chl.basic_get(queue='test')
            if method_frame:
                print('body: ', body)
                if body == item:
                    print("item found!")
                    msgs.append(body)
                    chl.basic_ack(method_frame.delivery_tag)
                    connection.close()
                    return msgs

            else:
                print("Message not found")
                connection.close()
                break
        return msgs

注意:我将其用于小型应用程序-队列中的消息少于50条。我不能说这个功能在大型应用程序中将如何发挥作用。