RabbitMQ + kombu:使用随机名称写入/读取一次性使用队列

时间:2017-10-01 09:40:45

标签: python rabbitmq message-queue kombu

我是新手处理消息交换并遇到问题,找到适合该任务的手册。

我需要组织一系列队列,以便:

  1. 生产者创建一些随机空队列并在那里写下所有消息包(通常是100条消息)。

  2. 消费者找到非空和非锁定队列并从中读取,直到 它是空的然后删除它并寻找下一个。

  3. 所以我的任务是使用消息作为包,我理解如何在一个队列中使用相同的密钥生成和使用,但无法找到如何使用队列池。

    我们可以让几个生产者和消费者并行运行,但不管他们中的哪一个发送给谁。 我们不需要也无法将特定生产者与特定消费者联系起来。

    一般任务:我们有很多客户端接收推送通知,我们将一些参数分组推送到以后作为组处理,所以这样的组应该在RabbitMQ中的一个队列中生成并且作为一个群体消费,但每个群体独立于其他群体。

    非常感谢Hannu的帮助:他简单而强大的解决方案的关键理念,我们可以拥有一个具有已知名称的持久队列,其中生产者将写入已创建队列的名称,消费者将读取这些名称从那里。

    为了使他的解决方案更具可读性和易用性以后在我的个人任务中,我将生产者中的publish_data()分成两个函数 - 一个制作随机队列并将其写入control_queue另一个接收这个random_queue并用消息填充它。类似的想法对于消费者来说是好的 - 一个处理队列的功能,另一个将被称为处理消息本身。

1 个答案:

答案 0 :(得分:1)

我做过类似的事,但是和Pika一起。我不得不为这些例子清理和制作旧的代码片段。它可能不是非常kombuish(这是我绝对使用它编写的第一个代码片段)但这就是我将如何解决它。基本上我会设置一个具有已知名称的控制队列。

发布者将为一包邮件创建随机队列名称,向其转储N条消息(在我的情况下为1-42),然后将队列名称发布到控制队列。然后,使用者接收此队列名称,绑定它,读取消息直到队列为空,然后删除队列。

这使事情变得相对简单,因为发布者不需要弄清楚他们在哪里发布他们的数据组(每个队列都是随机名称的新队列)。接收方不需要担心超时或“全部完成”消息,因为只有当一组数据已写入队列且每条消息都在等待时,接收方才会收到队列名称。

也没有必要修补锁或信号或其他任何会使事情复杂化的事情。您可以拥有任意数量的消费者和生产者。当然,使用交换和路由密钥可能会有不同的消费者群体用于不同的任务等。

<强>发布商

from kombu import Connection
import uuid
from time import sleep
def publish_data(conn):
    random_name= "q" + str(uuid.uuid4()).replace("-", "")
    random_queue = conn.SimpleQueue(random_name)
    for i in xrange(0, 42):
        random_queue.put(i)
    random_queue.close()
    return random_name


with Connection('amqp://guest:guest@localhost:5672//') as conn:
    control_queue = conn.SimpleQueue('control_queue')
    _a = 0
    while True:
        y_name = publish_data(conn)
        message = y_name
        control_queue.put(message)
        print('Sent: {0}'.format(message))
        _a += 1
        sleep(0.3)
        if _a > 20:
            break

    control_queue.close()

<强>消费

from Queue import Empty

from kombu import Connection, Queue


def process_msg(foo):
    print str(foo)
    with Connection("amqp://guest:guest@localhost:5672//") as _conn:
        sub_queue = _conn.SimpleQueue(str(foo))
        while True:
            try:
                _msg = sub_queue.get(block=False)
                print _msg.payload
                _msg.ack()
            except Empty:
                break
        sub_queue.close()
        chan = _conn.channel()
        dq = Queue(name=str(foo), exchange="")
        bdq = dq(chan)
        bdq.delete()


with Connection('amqp://guest:guest@localhost:5672//') as conn:
    rec = conn.SimpleQueue('control_queue')
    while True:
        msg = rec.get(block=True)
        entry = msg.payload
        msg.ack()
        process_msg(entry)