Проблема: веб-додаток гальмує через фонові завдання
Ваш додаток зависає, коли користувач надсилає 1000 листів? PDF-генерація блокує відповідь сервера на 30 секунд? Клієнти йдуть через довге завантаження? Типова картина на стартапах і enterprise: HTTP-запит має дочекатися завершення всіх операцій. Рішення — винести важкі завдання з синхронного циклу в асинхронні воркери через брокер повідомлень. RabbitMQ — промисловий брокер на протоколі AMQP, що витримує десятки тисяч повідомлень за секунду із затримкою менше 100 мікросекунд. За роки роботи ми налаштували черги для 70+ проєктів: від інтернет-магазинів до фінтех-сервісів. Ми розгортаємо RabbitMQ під ключ для веб-додатків на PHP, Node.js, Python і Go — з full-стек інтеграцією та моніторингом.
Що вирішуємо за допомогою черг
- Блокуючі операції — надсилання email, генерація звітів, розпізнавання зображень ідуть у воркери. Користувач не чекає.
- Втрата повідомлень — при падінні воркера повідомлення залишається в черзі. Dead Letter Queue ловить «биті» завдання.
- Масштабування — додаємо воркери горизонтально без зміни коду. Prefetch count регулює навантаження.
Чому RabbitMQ краще самописної черги?
Самописна черга на MySQL або Redis часто програє RabbitMQ за трьома параметрами: гарантії доставки, гнучкість маршрутизації та моніторинг. RabbitMQ використовує протокол AMQP — промисловий стандарт із підтвердженнями (ack/nack), dead-lettering і транзакціями. На відміну від Redis черги, RabbitMQ не втрачає дані при перезавантаженні завдяки persistent сховищу. А гнучка маршрутизація через topic exchange дозволяє направляти різні типи завдань в окремі черги за routing key: emails.welcome → черга листів, notifications.push → черга пушів. Один exchange обслуговує всі типи завдань без дублювання коду.
| Тип exchange | Маршрутизація | Приклад використання |
|---|---|---|
| direct | Точний збіг routing key | Критичні завдання з високим пріоритетом |
| topic | Шаблони * і # |
Гнучкий розподіл за типами (emails.*) |
| fanout | Всім підписникам | Широкомовні сповіщення |
| headers | За заголовками повідомлення | Складна логіка на основі метаданих |
Як налаштувати Dead Letter Queue для надійності?
DLQ — це черга для повідомлень, які не вдалося обробити після вичерпання спроб. Налаштовуємо аргументи x-dead-letter-exchange і x-dead-letter-routing-key при оголошенні основної черги. Якщо воркер відхиляє повідомлення (nack з requeue=false) або перевищено TTL, повідомлення переходить у DLQ. Там його можна проаналізувати та переслати вручну. Ми використовуємо DLQ у всіх проєктах — це обов'язковий елемент надійності. Також корисний x-message-ttl для завдань із терміном дії.
Детальніше про налаштування кластера для відмовостійкості
Для високої доступності розгортаємо кластер із 3 нод RabbitMQ. Використовуємо політики дзеркалювання черг (ha-mode: exactly, ha-params: 2). Тоді при падінні однієї ноди повідомлення не втрачаються, а клієнти автоматично перепідключаються через довгі AMQP-з'єднання. Налаштовуємо healthcheck та алерти в Grafana/Slack. Час виявлення збою — менше 5 секунд.
Що входить у налаштування RabbitMQ під ключ
- Встановлення та конфігурація RabbitMQ (Docker Compose або bare metal)
- Створення exchanges, черг, binding'ів під вашу бізнес-логіку
- Налаштування Dead Letter Queue і політик повторних спроб
- Інтеграція з вашим кодом (PHP, Node.js, Python, Go)
- Моніторинг через Management UI та алерти (Grafana + Slack)
- Документація: схема топології, опис черг, інструкція для розробників
- Навчання команди: як додавати нові завдання
Реалізація producer і consumer: PHP (php-amqplib) і Node.js (amqplib)
Наводимо робочий код для двох популярних мов. Producer публікує повідомлення в exchange з routing key, consumer слухає чергу та підтверджує обробку.
// PHP: Публікація повідомлення (скорочено) use PhpAmqpLib\Connection\AMQPStreamConnection; use PhpAmqpLib\Message\AMQPMessage; class RabbitMQPublisher { private $channel; public function __construct() { $this->channel = (new AMQPStreamConnection( config('rabbitmq.host'), 5672, config('rabbitmq.user'), config('rabbitmq.password'), config('rabbitmq.vhost', '/') ))->channel(); $this->setup(); } private function setup(): void { $this->channel->exchange_declare('myapp.exchange', 'topic', durable: true, auto_delete: false); $this->channel->queue_declare('myapp.emails', durable: true, arguments: new \PhpAmqpLib\Wire\AMQPTable([ 'x-dead-letter-exchange' => '', 'x-dead-letter-routing-key' => 'myapp.dlq', 'x-message-ttl' => 86400000, ])); $this->channel->queue_bind('myapp.emails', 'myapp.exchange', 'emails.*'); } public function publish(string $routingKey, array $payload): void { $msg = new AMQPMessage(json_encode($payload), [ 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT, 'content_type' => 'application/json', ]); $this->channel->basic_publish($msg, 'myapp.exchange', $routingKey); } } $publisher = new RabbitMQPublisher(); $publisher->publish('emails.welcome', ['user_id' => 42, 'email' => '[email protected]']); // Node.js: Consumer (скорочено) import amqp from 'amqplib'; async function consume() { const conn = await amqp.connect({ hostname: process.env.RABBITMQ_HOST, username: process.env.RABBITMQ_USER, password: process.env.RABBITMQ_PASS, vhost: process.env.RABBITMQ_VHOST, }); const ch = await conn.createChannel(); await ch.prefetch(5); await ch.consume('myapp.emails', async (msg) => { if (!msg) return; try { const payload = JSON.parse(msg.content.toString()); // обробити email await sendEmail(payload); ch.ack(msg); } catch (e) { console.error(e); ch.nack(msg, false, false); // надіслати в DLQ } }); } Інтеграція з Laravel: легкий шлях
Використовуємо пакет vladimir-yuldashev/laravel-queue-rabbitmq. Налаштування в .env і config/queue.php. Далі працюємо зі стандартними Job — Laravel сам публікує їх у чергу RabbitMQ.
QUEUE_CONNECTION=rabbitmq RABBITMQ_QUEUE=myapp.jobs RABBITMQ_EXCHANGE=myapp.exchange RABBITMQ_EXCHANGE_TYPE=topic RABBITMQ_ROUTING_KEY=jobs.* Як ми розгортаємо RabbitMQ: Docker Compose і безпека
Використовуємо офіційний образ rabbitmq:3.13-management-alpine. Він включає Management UI на порту 15672 — для моніторингу черг у реальному часі.
# docker-compose.yml services: rabbitmq: image: rabbitmq:3.13-management-alpine environment: RABBITMQ_DEFAULT_USER: myapp RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD} RABBITMQ_DEFAULT_VHOST: myapp volumes: - rabbitmq_data:/var/lib/rabbitmq ports: - "5672:5672" # AMQP - "15672:15672" # Management UI healthcheck: test: ["CMD", "rabbitmq-diagnostics", "ping"] interval: 10s timeout: 5s retries: 5 volumes: rabbitmq_data: Етапи роботи: покроковий план
- Аналітика — вивчаємо вашу бізнес-логіку, виявляємо вузькі місця, проєктуємо топологію черг.
- Розгортання — встановлюємо RabbitMQ (Docker або bare metal), налаштовуємо кластер для відмовостійкості.
- Інтеграція — пишемо producer'ів та consumer'ів, підключаємо DLQ, налаштовуємо prefetch.
- Моніторинг — підключаємо Management UI, налаштовуємо алерти в Slack/Telegram.
- Навантажувальне тестування — перевіряємо пропускну здатність (зазвичай до 10 000 msg/s на одній ноді).
Орієнтовні терміни
| Завдання | Термін |
|---|---|
| RabbitMQ + базовий producer/consumer | 2–3 дні |
| Laravel Queue інтеграція | 1–2 дні |
| Dead Letter Queue + моніторинг | +1–2 дні |
| HA кластер RabbitMQ (3 ноди) | 3–4 дні |
RabbitMQ vs Kafka: коли що обрати?
RabbitMQ кращий для веб-додатків з різними типами завдань і гнучкою маршрутизацією. Kafka — для потоків даних з високою пропускною здатністю (мільйони подій/сек) і довгим зберіганням. У типовому web-проєкті RabbitMQ простіший у налаштуванні та підтримці. Згідно з офіційною документацією RabbitMQ, брокер забезпечує затримку менше 100 мкс при низькому навантаженні. Ми гарантуємо стабільну роботу черг під навантаженням до 10 000 повідомлень/с без втрат.
Наш досвід і гарантії
За роки роботи ми налаштували черги для проєктів різного масштабу: від стартапів (1000 повідомлень/день) до enterprise (1 млн+ повідомлень/день). Досвід з PHP, Node.js, Python, Go. Всі проєкти проходять навантажувальне тестування та перевірку на витік пам'яті. Ми даємо гарантію на коректну роботу топології та відсутність втрати повідомлень при штатних сценаріях.
Для оцінки вашого проєкту зв'яжіться з нами — ми підготуємо конфігурацію за 1 день. Отримайте консультацію щодо інтеграції RabbitMQ у ваш додаток.







