Комбу: получить объект Queue, не зная его имени, но зная обмен, с которым он связан, и его ключ маршрутизации - PullRequest
0 голосов
/ 12 апреля 2020

Используя Kombu и RabbitMQ, я легко могу создать очередь и добавить в нее некоторые сообщения следующим образом:

#!/usr/bin/python3

from kombu import Connection, Queue, Exchange, Producer

URL = "pyamqp://user:password@localhost/vhost" # anonymised for posting

xname = "kombu.test.exchange"
qname = "kombu.test.queue"
rkey = "kombu.test.queue.routing.key"

with Connection(URL) as conn:
    # Connection is lazy. Force a connection now.
    conn.connect()
    c = conn.connection
    laddr = c.sock.getsockname()
    raddr = c.sock.getpeername()
    c.name = f"{laddr[0]}:{laddr[1]} -> {raddr[0]}:{raddr[1]}"
    c.name_short = f"{laddr[0]}:{laddr[1]}"

    print(f'Connection: {c.name_short}')

    # Create a channel on the conection and log it in the RabbitMQ webmonitor format                     
    ch = c.channel()
    ch.name = f'{c.name} ({ch.channel_id})'
    ch.name_short = f'{c.name_short} ({ch.channel_id})'

    print(f'Channel: {ch.name_short}')

    x = Exchange(xname, channel=ch)
    x.declare() # Makes the exchange appears on the RabbitMQ web monitor

    q = Queue(qname, exchange=x, channel=ch, routing_key=rkey, durable=True)
    q.declare() # Makes the queue appears on the RabbitMQ web monitor

    print(f'Exchange: {x.name}')
    print(f'Queue: {q.name}')
    print(f'Routing Key: {rkey}')

    p = Producer(ch)

    p.publish("message 1", exchange=x, routing_key=rkey)
    p.publish("message 2", exchange=x, routing_key=rkey)
    p.publish("message 3", exchange=x, routing_key=rkey)
    p.publish("message 4", exchange=x, routing_key=rkey)
    p.publish("message 5", exchange=x, routing_key=rkey)

Используя веб-монитор RabbitMQ , я вижу Exchange, очередь и что в очереди 5 сообщений. Прекрасно.

Теперь я хотел бы прочитать эти сообщения. Но если вы изучите приведенный выше код, вы заметите, что для отправки сообщений в очередь нам не нужно знать имя очереди. На самом деле, нам просто нужно знать обмен, с которым он связан, и ключ_рассылки, который его достигнет.

Я также легко могу видеть их на веб-мониторе RabbitMQ. RabbitMQ Exchange Bindings

Так что я хотел бы также прочитать эти сообщения, не зная имени очереди, используя только Exchange и ключ маршрутизации.

Вот заглушка, с которой я экспериментирую (я даю соединение и канал имя и short_name, которое соответствует тому, что отображает веб-монитор RabbitMQ, чтобы облегчить их поиск там):

#!/usr/bin/python3

from kombu import Connection, Queue, Exchange, Consumer

URL = "pyamqp://user:password@localhost/vhost" # anonymised for posting

xname = "kombu.test.exchange"
rkey = "kombu.test.queue.routing.key"

with Connection(URL) as conn:
    # Connection is lazy. Force a connection now.
    conn.connect()
    c = conn.connection
    laddr = c.sock.getsockname()
    raddr = c.sock.getpeername()
    c.name = f"{laddr[0]}:{laddr[1]} -> {raddr[0]}:{raddr[1]}"
    c.name_short = f"{laddr[0]}:{laddr[1]}"

    print(f'Connection: {c.name_short}')

    # Create a channel on the conection and log it in the RabbitMQ webmonitor format                     
    ch = c.channel()
    ch.name = f'{c.name} ({ch.channel_id})'
    ch.name_short = f'{c.name_short} ({ch.channel_id})'

    print(f'Channel: {ch.name_short}')

    x = Exchange(xname, channel=ch)
    x.declare() # Makes the exchange appears on the RabbitMQ web monitor

    q = What #?

И это то, где я застрял, после большого поиска в Интернете и в документах.

Самый близкий намек на то, что у Exchange есть метод привязки:

    b = x.binding()

Но, увы, это, похоже, не помогает, я не вижу в b списка списков очередей, например, по ключу маршрутизации.

Я пытался просто объявить очередь:

    q = Queue(exchange=x, channel=c, routing_key=rkey)

Но тоже не повезло. Это не Очередь, за которой я иду.

Но мне нужен объект Queue, чтобы я мог:

  1. вызвать get () для проверки сообщений
  2. создать получателя в очереди

Но, к сожалению, я не могу найти Очередь с помощью routing_key. Это должно быть возможно, как-то я понимаю. Издатели могут сделать это. Почему Потребитель не может сделать это?

...