RabbitMQ — это брокер сообщений, который помогает приложениям общаться асинхронно. Если вы пишете на PHP и хотите разгрузить тяжёлые задачи или связать микросервисы, эта статья для вас. Разберём всё по шагам: от установки до рабочего кода.

Digital-студия WNDER

Зачем PHP нужен RabbitMQ

Представьте: пользователь загружает фото, а сервер должен сгенерировать три миниатюры. Если делать это сразу, страница будет грузиться вечность. С очередями PHP-скрипт быстро кладёт задачу в RabbitMQ и отвечает пользователю «всё ок». А отдельный процесс-воркер спокойно обрабатывает фото в фоне. Красота!

RabbitMQ работает по протоколу AMQP. PHP общается с ним через библиотеку php-amqplib. Она стабильная и простая.

Установка и настройка

Сначала установите RabbitMQ. На Ubuntu это одна команда:

sudo apt install rabbitmq-server

Затем добавьте библиотеку в проект через Composer:

composer require php-amqplib/php-amqplib

Теперь можно подключаться. По умолчанию RabbitMQ слушает порт 5672, логин и пароль — guest.

Отправка сообщения в очередь

Классический пример: скрипт отправляет задачу на генерацию PDF. Создаём подключение, канал, объявляем очередь и публикуем сообщение.

<?php
require_once __DIR__ . '/vendor/autoload.php';

use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

// Подключаемся к RabbitMQ
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

// Объявляем очередь (если её нет, она создастся)
$channel->queue_declare('pdf_queue', false, false, false, false);

// Формируем сообщение
$data = json_encode(['user_id' => 42, 'template' => 'invoice']);
$msg = new AMQPMessage($data, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);

// Публикуем
$channel->basic_publish($msg, '', 'pdf_queue');

echo "Сообщение отправлено\n";

$channel->close();
$connection->close();

Обратите внимание на delivery_mode = 2 — это делает сообщение persistent (устойчивым к перезагрузке брокера).

Как получать сообщения (воркер)

Воркер — это скрипт, который висит в фоне и ждёт сообщения. Он подписывается на очередь и обрабатывает каждое сообщение.

<?php
require_once __DIR__ . '/vendor/autoload.php';

use PhpAmqpLib\Connection\AMQPStreamConnection;

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

$channel->queue_declare('pdf_queue', false, false, false, false);

echo " [*] Ожидание сообщений. Для выхода нажмите CTRL+C\n";

$callback = function ($msg) {
    $data = json_decode($msg->body, true);
    echo "Получено: " . print_r($data, true) . "\n";
    // Здесь имитация долгой работы
    sleep(2);
    echo "Обработано\n";
    // Подтверждаем обработку
    $msg->ack();
};

$channel->basic_consume('pdf_queue', '', false, false, false, false, $callback);

while ($channel->is_open()) {
    $channel->wait();
}

$channel->close();
$connection->close();

Метод ack() говорит брокеру, что сообщение успешно обработано. Если воркер упадёт до ack, RabbitMQ вернёт сообщение в очередь и его получит другой воркер.

Правило: Всегда подтверждайте сообщения (ack) только после успешной обработки. Иначе при сбое задачи будут потеряны.

Полезные параметры и советы

Вот таблица с основными параметрами, которые вы будете использовать при объявлении очереди и отправке сообщений.

Параметр Где используется Что делает
queue_declare($queue, $passive, $durable, $exclusive, $auto_delete) Канал Создаёт очередь. $durable = true — очередь переживёт перезагрузку RabbitMQ.
delivery_mode AMQPMessage 1 — transient (может потеряться), 2 — persistent (сохраняется на диск).
basic_qos($prefetch_size, $prefetch_count, $global) Канал Ограничивает число неподтверждённых сообщений у воркера. Полезно для равномерной нагрузки.
basic_consume($queue, $consumer_tag, $no_local, $no_ack, $exclusive, $no_wait, $callback) Канал Подписывает на очередь. $no_ack = false — включает ручное подтверждение.

Ещё лайфхак: используйте basic_qos с prefetch_count = 1, чтобы воркер не захватывал сразу много сообщений. Так нагрузка распределится честнее.

Совет: Для обработки ошибок оберните логику в try-catch. Если сообщение «битое» и не обрабатывается, отправьте его в отдельную очередь для анализа (dead letter queue).

Что в итоге

RabbitMQ + PHP — это мощная связка для асинхронных задач. Вы научились подключаться к брокеру, отправлять и получать сообщения, настраивать надёжность. Главное — не забывайте про подтверждения и постоянные сообщения, если важна сохранность данных. Пробуйте, экспериментируйте, и очереди сделают ваше приложение быстрее и устойчивее.

Студия WNDER