Ответ
RabbitMQ — это популярный опенсорсный брокер сообщений, реализующий и расширяющий протокол AMQP (Advanced Message Queuing Protocol). Он выступает в роли промежуточного слоя (middleware), который принимает, хранит, маршрутизирует и доставляет сообщения между независимыми приложениями или сервисами.
Решаемые проблемы:
- Связность (Decoupling): Отправитель (Producer) и получатель (Consumer) не знают друг о друге и работают асинхронно.
- Буферизация (Buffering): Брокер накапливает сообщения, если потребитель временно не готов, сглаживая пиковые нагрузки.
- Гарантированная доставка (Reliability): Подтверждения (acknowledgements), persistence сообщений на диск.
- Гибкая маршрутизация (Routing): Разные типы обменников (exchanges) позволяют реализовать сложные сценарии (публикация/подписка, маршрутизация по ключу).
Базовая архитектура AMQP в RabbitMQ:
Producer --> Exchange --(Binding/Routing Key)--> Queue --> Consumer
- Exchange получает сообщения от продюсера и решает, в какие очереди их направить. Основные типы:
direct(доставка по точному совпадению ключа маршрутизации).fanout(рассылка во все привязанные очереди).topic(доставка по шаблону ключа).headers(доставка по заголовкам сообщения).
- Queue — это именованный буфер, хранящий сообщения до их обработки потребителем.
- Binding — это правило, связывающее exchange с очередью.
Пример на C# (с использованием библиотеки RabbitMQ.Client):
// 1. PRODUCER (Отправка лога)
using RabbitMQ.Client;
var factory = new ConnectionFactory() { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
// Объявляем exchange типа 'direct' с именем 'logs'
channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Direct);
var severity = "error"; // Ключ маршрутизации
var message = $"[{DateTime.UtcNow}] Critical error in module X.";
var body = Encoding.UTF8.GetBytes(message);
// Публикуем сообщение в exchange 'logs' с ключом 'error'
channel.BasicPublish(exchange: "logs",
routingKey: severity,
basicProperties: null,
body: body);
Console.WriteLine($" [x] Sent '{severity}':'{message}'");
// 2. CONSUMER (Получение только ошибок)
// ... (создание connection и channel аналогично)
// Объявляем тот же exchange
channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Direct);
// Создаём временную (exclusive) очередь с автоматическим именем
var queueName = channel.QueueDeclare().QueueName;
// Привязываем очередь к exchange 'logs' с ключом 'error'
channel.QueueBind(queue: queueName,
exchange: "logs",
routingKey: "error");
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var receivedBody = ea.Body.ToArray();
var receivedMessage = Encoding.UTF8.GetString(receivedBody);
Console.WriteLine($" [x] Received '{ea.RoutingKey}':'{receivedMessage}'");
// Ручное подтверждение обработки
channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
};
// Начинаем потребление с отключением autoAck
channel.BasicConsume(queue: queueName,
autoAck: false, // Важно для надёжности!
consumer: consumer);
Почему RabbitMQ? Он обеспечивает надёжную, гибкую и кросс-платформенную коммуникацию между сервисами, что является фундаментом для архитектур, основанных на микросервисах и событиях (Event-Driven Architecture).