RabbitMQ — один из самых популярных брокеров сообщений. Он принимает сообщения от одних сервисов и доставляет их другим, обеспечивая надёжную асинхронную коммуникацию между частями вашего приложения.
Например: пользователь загрузил видео, сайт сразу ответил «принято», а задача на обработку ушла в очередь. RabbitMQ передаст её воркеру, воркер обработает и задача не потеряется, при этом пользователю не нужно будет ждать выполнения.
В этой статье установим RabbitMQ на Ubuntu, настроим веб-интерфейс управления и разберём базовую конфигурацию.
RabbitMQ написан на Erlang, поэтому вместе с ним установится и Erlang-рантайм.
Если вы только купили сервер:
Подключитесь к серверу
Выполните подготовку сервера к работе
sudo apt update && sudo apt upgrade -y
Устанавливаем
sudo apt install -y erlang rabbitmq-server
Установка может занять некоторое время, т.к. Erlang весит прилично. После завершения RabbitMQ запустится автоматически.
Проверяем статус:
sudo systemctl status rabbitmq-server
Должно быть Active: active (running). Добавляем в автозагрузку, если не добавлен:
sudo systemctl enable rabbitmq-server
RabbitMQ поставляется с удобной веб-консолью — Management Plugin. По умолчанию она отключена, включаем:
sudo rabbitmq-plugins enable rabbitmq_management
Перезапускаем RabbitMQ, чтобы плагин активировался:
sudo systemctl restart rabbitmq-server
Веб-интерфейс будет доступен по адресу http://ваш_ip:15672.
Совет: Management Plugin добавляет HTTP API поверх RabbitMQ. Через него можно управлять очередями программно, что бывает очень удобно для автоматизации.
По умолчанию в RabbitMQ есть пользователь guest, но он работает только с localhost, подключиться через браузер с другого IP не получится. Это сделано в целях безопасности.
Создаём нового пользователя:
sudo rabbitmqctl add_user admin ВашНадёжныйПароль
Назначаем роль администратора:
sudo rabbitmqctl set_user_tags admin administrator
Даём полные права на все виртуальные хосты:
sudo rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
Теперь заходим в веб-интерфейс http://ваш_ip:15672 под созданным пользователем.
Virtual Host (vhost) — изолированное пространство внутри RabbitMQ. Разные приложения могут работать в разных vhost и не мешать друг другу. По умолчанию существует vhost /.
Exchange — точка входа для сообщений. Приложение отправляет сообщение не напрямую в очередь, а в exchange. Exchange решает, в какую очередь оно пойдёт по правилам маршрутизации.
Queue — очередь, где сообщения хранятся до момента обработки.
Binding — связь между exchange и очередью. Определяет, какие сообщения из exchange попадут в конкретную очередь.
Consumer — приложение, которое читает сообщения из очереди и обрабатывает их.
Схема работы: Producer → Exchange → (Binding) → Queue → Consumer.
Создадим отдельный vhost для каждого приложения. Это изолирует очереди и упрощает управление правами.
sudo rabbitmqctl add_vhost my_app
Создаём отдельного пользователя для приложения:
sudo rabbitmqctl add_user my_app_user ПарольПриложения
Даём ему права только на нужный vhost:
sudo rabbitmqctl set_permissions -p my_app my_app_user ".*" ".*" ".*"
Теперь my_app_user видит только очереди в my_app и не имеет доступа к остальному. Именно эти credentials используйте в коде приложения.
Покажем, как отправить и получить сообщение на Python и Node.js.
pip install pika
Отправка сообщения (Producer):
import pika
connection = pika.BlockingConnection(
pika.ConnectionParameters(
host='ваш_ip',
port=5672,
virtual_host='my_app',
credentials=pika.PlainCredentials('my_app_user', 'ПарольПриложения')
)
)
channel = connection.channel()
# Создаём очередь (если не существует — создастся автоматически)
delivery_mode=2 # Сообщение сохранится на диск и не потеряется при перезапуске
)
)
print('Сообщение отправлено')
connection.close()
Например, 3 раза мы отправили сообщение
Это тут же отобразилось в веб интерфейсе
Получение сообщения (Consumer):
import pika
connection = pika.BlockingConnection(
pika.ConnectionParameters(
host='ваш_ip',
port=5672,
virtual_host='my_app',
credentials=pika.PlainCredentials('my_app_user', 'ПарольПриложения')
)
)
channel = connection.channel()
channel.queue_declare(queue='tasks', durable=True)
# Не давать больше одной задачи за раз — пока не обработает текущую
channel.basic_qos(prefetch_count=1)
def callback(ch, method, properties, body):
print(f'Получено: {body.decode()}')
# После обработки подтверждаем получение
ch.basic_ack(delivery_tag=method.delivery_tag)
channel.basic_consume(queue='tasks', on_message_callback=callback)
print('Ожидаем сообщений...')
channel.start_consuming()
Запускаем и получаем все 3 сообщения
В веб интерфейсе тоже это отобразится
Важно: параметр
delivery_mode=2иdurable=Trueработают в паре. Первый сохраняет сообщение на диск, второй переживает перезапуск RabbitMQ. Без обоих — сообщения могут потеряться при падении сервера.
npm install amqplib
Отправка:
import amqp from 'amqplib';
const connection = await amqp.connect({
protocol: 'amqp',
hostname: 'ваш_ip',
port: 5672,
username: 'my_app_user',
password: 'ПарольПриложения',
vhost: 'my_app',
});
const channel = await connection.createChannel();
await channel.assertQueue('tasks', { durable: true });
channel.sendToQueue(
'tasks',
Buffer.from('Привет, воркер!'),
{ persistent: true }
);
console.log('Сообщение отправлено');
await connection.close();
Получение:
import amqp from 'amqplib';
const connection = await amqp.connect({
protocol: 'amqp',
hostname: 'ваш_ip',
port: 5672,
username: 'my_app_user',
password: 'ПарольПриложения',
vhost: 'my_app',
});
const channel = await connection.createChannel();
await channel.assertQueue('tasks', { durable: true });
channel.prefetch(1);
channel.consume('tasks', (msg) => {
if (msg !== null) {
console.log('Получено:', msg.content.toString());
channel.ack(msg);
}
});
console.log('Ожидаем сообщений...');
Представим реальную задачу:
Пользователь загрузил файл (видео / изображение / отчёт) , API должно ответить сразу, обработка должна идти в фоне
import pika
import json
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost')
)
channel = connection.channel()
channel.queue_declare(queue='tasks', durable=True)
task = {
"type": "resize_image",
"file": "photo.jpg"
}
channel.basic_publish(
exchange='',
routing_key='tasks',
body=json.dumps(task),
properties=pika.BasicProperties(delivery_mode=2)
)
print("Задача отправлена:", task)
connection.close()
API на этом заканчивает работу и отдаёт ответ пользователю
import pika
import json
import time
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost')
)
channel = connection.channel()
channel.queue_declare(queue='tasks', durable=True)
channel.basic_qos(prefetch_count=1)
def callback(ch, method, properties, body):
task = json.loads(body)
print("Обрабатываем:", task)
# имитация работы
time.sleep(3)
print("Готово:", task)
ch.basic_ack(delivery_tag=method.delivery_tag)
channel.basic_consume(queue='tasks', on_message_callback=callback)
print("Воркер ждёт задачи...")
channel.start_consuming()
Запустим например worker.py
В другой SSH сессии запустим producer.py
При запуске вы будете сразу же получать ответ, задача уйдет в worker, по выполнении получим сообщение, что задача выполнена
Так ваш API остаётся быстрым, задачи не блокируют общий поток, воркеры легко масштабируются
RabbitMQ использует несколько портов:
# AMQP — основной протокол для приложений
sudo ufw allow 5672/tcp
# Веб-интерфейс управления
sudo ufw allow 15672/tcp
Порт 5672 лучше открывать только для IP ваших серверов, а не всему интернету:
sudo ufw allow from ВАШ_IP to any port 5672
Веб-интерфейс на 15672 тоже стоит ограничить по IP или закрыть за Nginx с авторизацией, если сервер публичный.
Создадим файл конфигурации для тонкой настройки:
sudo nano /etc/rabbitmq/rabbitmq.conf
Полезные параметры для старта:
# Максимальный размер сообщения (в байтах) — по умолчанию 128 МБ
max_message_size = 134217728
# Порог памяти — при достижении RabbitMQ замедлит приём сообщений
vm_memory_high_watermark.relative = 0.6
# Порог диска — минимальный свободный остаток на диске
disk_free_limit.absolute = 1GB
# Отключаем гостевого пользователя полностью
loopback_users.guest = true
vm_memory_high_watermark.relative = 0.6 — RabbitMQ начнёт применять flow control (замедление), когда займёт 60% доступной памяти. Это защита от ситуации, когда брокер съедает всю память сервера и падает. На VDS с малым RAM можно снизить до 0.4.
disk_free_limit.absolute = 1GB — RabbitMQ остановит приём сообщений, если на диске останется меньше 1 ГБ. Лучше пусть приложение получит ошибку, чем сервер встанет намертво из-за полного диска.
Применяем конфигурацию:
sudo systemctl restart rabbitmq-server
Список всех очередей и количество сообщений в них:
sudo rabbitmqctl list_queues -p my_app name messages consumers
Список пользователей:
sudo rabbitmqctl list_users
Список виртуальных хостов:
sudo rabbitmqctl list_vhosts
Удалить все сообщения из очереди (осторожно):
sudo rabbitmqctl purge_queue tasks -p my_app
Посмотреть текущие соединения:
sudo rabbitmqctl list_connections user peer_host peer_port state
Проверить состояние кластера (если он есть):
sudo rabbitmqctl cluster_status
Посмотреть логи в реальном времени:
sudo journalctl -u rabbitmq-server -f