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