Что такое RabbitMQ?

«Что такое RabbitMQ?» — вопрос из категории Архитектура, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

RabbitMQ — это брокер сообщений с открытым исходным кодом, реализующий протокол AMQP (Advanced Message Queuing Protocol). Он выступает в роли промежуточного слоя ("почтового отделения") между независимыми приложениями или сервисами, позволяя им обмениваться сообщениями асинхронно и надежно.

Основные концепции:

  • Producer (Издатель): Приложение, которое отправляет сообщения.
  • Exchange (Обменник): Принимает сообщения от издателя и решает, в какие очереди их направить, на основе типа обменника и ключа маршрутизации (routing key).
  • Queue (Очередь): Буфер, в котором хранятся сообщения до их обработки.
  • Consumer (Потребитель): Приложение, которое получает и обрабатывает сообщения из очереди.

Типы обменников (Exchange):

  1. Direct: Сообщение идет в очередь, чей ключ привязки (binding key) точно совпадает с ключом маршрутизации.
  2. Fanout: Сообщение рассылается во все привязанные очереди (широковещание).
  3. Topic: Сообщение направляется в очереди, чей ключ привязки совпадает с ключом маршрутизации по шаблону (например, logs.*.error).

Пример на C++ с использованием библиотеки AMQP-CPP:

#include <amqpcpp.h>
#include <amqpcpp/libev.h>
#include <ev.h>

int main() {
    // Создаем обработчик событий (libev)
    auto *loop = EV_DEFAULT;
    AMQP::LibEvHandler handler(loop);

    // Устанавливаем соединение с брокером
    AMQP::TcpConnection connection(&handler, AMQP::Address("amqp://guest:guest@localhost/"));
    AMQP::TcpChannel channel(&connection);

    // Объявляем очередь с именем "task_queue"
    channel.declareQueue("task_queue", AMQP::durable); // durable - очередь сохранится после перезагрузки

    // Публикуем сообщение в очередь через дефолтный обменник (direct)
    channel.publish("", "task_queue", "Hello, RabbitMQ from C++!");
    std::cout << " [x] Sent 'Hello, RabbitMQ from C++!'" << std::endl;

    // Запускаем цикл событий для обработки сетевого ввода-вывода
    ev_run(loop, 0);

    return 0;
}

Зачем это нужно? RabbitMQ помогает:

  • Развязать сервисы: Продюсеру не нужно знать о существовании консьюмера.
  • Гарантировать доставку: Сообщения могут быть сохранены на диске (persistent).
  • Балансировать нагрузку: Несколько консьюмеров могут читать из одной очереди, распределяя работу.
  • Буферизовать запросы: Консьюмер может быть временно недоступен, но сообщения не потеряются.