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

Ответ

Да, это одна из фундаментальных возможностей 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): Если потребитель падает, не подтвердив сообщение, оно будет возвращено в очередь и передано другому свободному потребителю.

Ответ 18+ 🔞

Ну, слушай, вот тебе классика, блядь, RabbitMQ! Это как раз тот самый случай, когда можно просто взять и запустить кучу одинаковых работяг, и они будут мирно, по-братски, делить одну кучу работы. Паттерн этот умные дядьки назвали Competing Consumers — конкурирующие потребители, ёпта.

Как это работает, если на пальцах:

  • Распределовка (по дефолту — карусель): RabbitMQ, как заботливая мамка, по очереди суёт сообщения каждому из подписчиков. Первое — первому, второе — второму, третье — опять первому, и так по кругу, блядь.
  • Эксклюзив: Каждое сообщение достаётся строго одному чуваку из толпы. Два раза его не обработают, если всё настроено правильно, конечно.

Вот и весь секрет горизонтального масштабирования, ёбана! Хочешь быстрее жрать задачи? Запускай больше инстансов своего приложения-потребителя. Просто, как три копейки.

Вот тебе кусок кода на Python (pika), чтобы было понятнее, как такого работягу сделать:

import pika

# Функция, которая будет вмазывать по каждому пришедшему сообщению
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): Если твой работяга-потребитель внезапно накрылся медным тазом, не успев сказать «обработано», сообщение вернётся обратно в очередь и достанется кому-нибудь другому. Ничего не потеряется, красота!