Очереди задач для PHP: RabbitMQ, Gearman и PhpAmqpLib
В современных веб-приложениях критически важна скорость ответа пользователю. Длительные операции (отправка email, генерация PDF, обработка изображений, парсинг данных) не должны блокировать основной поток выполнения. Решение этой проблемы — очереди задач (job queues). Они позволяют делегировать фоновые задачи воркерам, работающим асинхронно.
В экосистеме PHP существует несколько зрелых решений для организации очередей. Рассмотрим три ключевых инструмента: PhpAmqpLib (клиент для RabbitMQ), Gearman и нативный RabbitMQ через его протокол AMQP.
Зачем нужны очереди задач в PHP?
Типичный сценарий: пользователь регистрируется на сайте. Система должна:
- Сохранить данные в БД
- Отправить приветственное письмо
- Создать PDF-договор
- Запустить проверку на спам
Без очереди пользователь ждет завершения всех операций. С очередью:
- Основной процесс сохраняет данные и отправляет задачу в очередь
- Пользователь мгновенно получает ответ «Успешно»
- Фоновые воркеры поочередно обрабатывают задачи
Это повышает UX и стабильность системы.
1. RabbitMQ и PhpAmqpLib
RabbitMQ — мощный брокер сообщений, поддерживающий протокол AMQP 0-9-1. PhpAmqpLib — чисто PHP-реализация клиента для работы с RabbitMQ без внешних расширений.
Установка
composer require php-amqplib/php-amqplib
Пример: Отправка задачи (Producer)
<?php
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
// Объявляем очередь (создастся, если не существует)
$channel->queue_declare('email_queue', false, true, false, false);
$data = json_encode([
'to' => 'user@example.com',
'subject' => 'Приветствие',
'body' => 'Добро пожаловать!'
]);
$msg = new AMQPMessage($data, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);
$channel->basic_publish($msg, '', 'email_queue');
echo " [x] Отправлено: $data\n";
$channel->close();
$connection->close();
Пример: Воркер (Consumer)
<?php
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('email_queue', false, true, false, false);
echo " [*] Ожидание задач. Для выхода нажмите CTRL+C\n";
$callback = function ($msg) {
$data = json_decode($msg->body, true);
// Имитация отправки email
echo " [x] Отправка письма на {$data['to']}: {$data['subject']}\n";
sleep(2); // Имитация работы
echo " [x] Готово\n";
$msg->ack(); // Подтверждение обработки
};
$channel->basic_qos(null, 1, null);
$channel->basic_consume('email_queue', '', false, false, false, false, $callback);
while ($channel->is_consuming()) {
$channel->wait();
}
Преимущества: надежность, поддержка сложных маршрутизаций (topics, headers), персистентность сообщений, кластеризация.
Недостатки: требуется установка и настройка RabbitMQ сервера (Erlang, управление через web-интерфейс).
2. Gearman
Gearman — система распределенных задач. Состоит из трех компонентов: клиент (отправляет задачи), воркер (выполняет), сервер (диспетчер). Работает через бинарный протокол.
Установка
Сначала установите сервер Gearman и PHP-расширение:
sudo apt-get install gearman-job-server
sudo pecl install gearman
Добавьте extension=gearman.so в php.ini.
Пример: Клиент
<?php
$client = new GearmanClient();
$client->addServer('127.0.0.1', 4730);
$data = json_encode([