В Pika или RabbitMQ, как проверить, если какие-либо потребители в настоящее время потребляют?

Я хотел бы проверить, если Потребитель/Работник присутствует, чтобы потреблять Я собираюсь отправить.

если их нет работник, Я бы начал некоторых рабочих (как потребители, так и издатели находятся на одной машине), а затем перейти к публикации сообщения.

если есть такая функция, как connection.check_if_has_consumers, Я бы реализовал его примерно так -

import pika
import workers

# code for publishing to worker queue
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

# if there are no consumers running (would be nice to have such a function)
if not connection.check_if_has_consumers(queue="worker_queue", exchange=""):
    # start the workers in other processes, using python's `multiprocessing`
    workers.start_workers()

# now, publish with no fear of your queues getting filled up
channel.queue_declare(queue="worker_queue", auto_delete=False, durable=True)
channel.basic_publish(exchange="", routing_key="worker_queue", body="rockin",
                            properties=pika.BasicProperties(delivery_mode=2))
connection.close()

но я не могу найти любой функция с check_if_has_consumers функциональные возможности пищуха.

есть ли способ выполнить это, используя пищуха? или, может быть, путем говорить to Кролик напрямую?

Я не совсем уверен, но я думаю RabbitMQ будет знать о количестве потребителей, подписанных на разные очереди, так как он отправляет сообщения к ним и принимает acks

Я только начал с RabbitMQ 3 часа назад... любая помощь приветствуется...

вот workers.py код я написал, Если это поможет....

import multiprocessing
import pika


def start_workers(num=3):
    """start workers as non-daemon processes"""
    for i in xrange(num):    
        process = WorkerProcess()
        process.start()


class WorkerProcess(multiprocessing.Process):
    """
    worker process that waits infinitly for task msgs and calls
    the `callback` whenever it gets a msg
    """
    def __init__(self):
        multiprocessing.Process.__init__(self)
        self.stop_working = multiprocessing.Event()

    def run(self):
        """
        worker method, open a channel through a pika connection and
        start consuming
        """
        connection = pika.BlockingConnection(
                              pika.ConnectionParameters(host='localhost')
                     )
        channel = connection.channel()
        channel.queue_declare(queue='worker_queue', auto_delete=False,
                                                    durable=True)

        # don't give work to one worker guy until he's finished
        channel.basic_qos(prefetch_count=1)
        channel.basic_consume(callback, queue='worker_queue')

        # do what `channel.start_consuming()` does but with stopping signal
        while len(channel._consumers) and not self.stop_working.is_set():
            channel.transport.connection.process_data_events()

        channel.stop_consuming()
        connection.close()
        return 0

    def signal_exit(self):
        """exit when finished with current loop"""
        self.stop_working.set()

    def exit(self):
        """exit worker, blocks until worker is finished and dead"""
        self.signal_exit()
        while self.is_alive(): # checking `is_alive()` on zombies kills them
            time.sleep(1)

    def kill(self):
        """kill now! should not use this, might create problems"""
        self.terminate()
        self.join()


def callback(channel, method, properties, body):
    """pika basic consume callback"""
    print 'GOT:', body
    # do some heavy lifting here
    result = save_to_database(body)
    print 'DONE:', result
    channel.basic_ack(delivery_tag=method.delivery_tag)

EDIT:

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

и RabbitMQ эти API управления HTTP, они работают после того, как вы включили модуль управления и в середине страницы http apis есть

/ api / connections-список всех открытых соединений.

/ api / connections / name-индивидуальное соединение. Удаление его закроет соединение.

Итак, если я подключу мой работники и меня производит как по-разному подключение имена / пользователи, я смогу проверить если the Работник Связи открыта... (могут возникнуть проблемы, когда работник умирает...)

будет ждать лучшего решения...

EDIT:

просто нашел это в документах rabbitmq, но это было бы хакерски сделать в python:

shobhit@oracle:~$ sudo rabbitmqctl -p vhostname list_queues name consumers
Listing queues ...
worker_queue    0
...done.

так что я мог бы сделать что-то вроде

subprocess.call("echo password|sudo -S rabbitmqctl -p vhostname list_queues name consumers | grep 'worker_queue'")

суховато... все еще надеюсь, что у pika есть функция python для этого...

спасибо,

2 ответов


Я как раз изучал это. После прочтения источника и документов я наткнулся на следующее: channel.py:

@property
def consumer_tags(self):
    """Property method that returns a list of currently active consumers

    :rtype: list

    """
    return self._consumers.keys()

мое собственное тестирование прошло успешно. Я использовал следующее, Где мой объект канала является self._channel:

if len(self._channel.consumer_tags) == 0:
        LOGGER.info("Nobody is listening.  I'll come back in a couple of minutes.")
        ...

Я действительно нашел это случайно, ища другую проблему, но одна вещь, которая может помочь вам, находится в функции Basic_Publish, есть параметр "Immediate", который по умолчанию равен False.

одна идея, которую вы могли бы сделать, - установить флаг Immediate в True, который потребует, чтобы он был немедленно потреблен потребителем, а не сидел в очереди. Если работник не доступен для использования сообщения, он будет отбрасывать ошибку, сообщая вам, чтобы начать другой работник.

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