Проблема: веб-додаток гальмує через фонові завдання
Ваш додаток зависає, коли користувач надсилає 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 у ваш додаток.







