Возможна ли обработка сообщений из одной очереди RabbitMQ несколькими потребителями

«Возможна ли обработка сообщений из одной очереди RabbitMQ несколькими потребителями» — вопрос из категории Брокеры сообщений, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, это одна из фундаментальных возможностей RabbitMQ, реализующая паттерн Competing Consumers (Конкурирующие потребители).

Когда несколько потребителей (consumers) подписываются на одну и ту же очередь, RabbitMQ распределяет входящие сообщения между ними.

Принцип работы:

  • Распределение (по умолчанию Round-Robin): Сообщения поочередно отправляются каждому из подписчиков.
  • Эксклюзивная доставка: Каждое конкретное сообщение доставляется только одному потребителю из группы.

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

Пример кода потребителя (Python с pika):

import pika

# Callback-функция для обработки сообщения
def callback(ch, method, properties, body):
    print(f" [x] Получено {body.decode()}")
    # Имитация обработки
    # ...
    ch.basic_ack(delivery_tag=method.delivery_tag)

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

channel.queue_declare(queue='task_queue', durable=True)

# Не отправлять новое сообщение, пока предыдущее не обработано
channel.basic_qos(prefetch_count=1)

channel.basic_consume(queue='task_queue', on_message_callback=callback)

print(' [*] Ожидание сообщений. Для выхода нажмите CTRL+C')
channel.start_consuming()

Ключевые моменты:

  • Чтобы запустить нескольких потребителей, вы запускаете этот скрипт в нескольких отдельных процессах или на разных машинах.
  • prefetch_count=1 критически важен для справедливого распределения. Он гарантирует, что RabbitMQ не будет отправлять потребителю больше одного сообщения за раз, пока тот не подтвердит (ack) обработку текущего.
  • Подтверждение (ack): Если потребитель падает, не подтвердив сообщение, оно будет возвращено в очередь и передано другому свободному потребителю.