В этой статье мы расскажем об альтернативном подключении очередей и о том, как мы можем использовать несколько разных очередей для разных задач, а также, как можно расставлять приоритеты задач/очередей. Надеюсь, вы уже прочитали первую часть этой статьи.
RabbitMQ
Хотя Laravel-сообщество обычно выбирает для подключения Redis, но мы будем использовать RabbitMQ.
Я решил выбрать его по следующим причинам:
- другие подключения и так довольно хорошо документированы (взгляните на horizon, официальный laravel-пакет для Redis-очередей)
- по собственному опыту — RabbitMQ круче других подключений
- если вы читаете эту статью, то скорее всего, вы новичок в мире Задач и Очередей, поэтому лучше сосредоточиться на изучении того, как с ними обращаться, чем заморачиваться как установить Redis и как заставить его работать и на локальном компьютере и на продакшн-сервере. А с RabbitMQ мы можем использовать стороннюю службу, которая сделает это за нас. Мой любимый сервис — cloudAMQP.com. Его бесплатного плана (1 миллион задач в месяц, 100 очередей) более чем достаточно для этого урока, да и для большинства ваших пет-проектов.
Настройка очереди
Зарегистрируйтесь на cloudamqp.com и создайте экземпляр «Little Lemur».
После чего, вы получите подробную информацию:
теперь нам нужно сказать Laravel, что мы хотим для наших задач использовать RabbitMQ.
Для начала нам нужно добавить следующий пакет: vladimir-yuldashev/laravel-queue-rabbitmq
composer require vladimir-yuldashev/laravel-queue-rabbitmq
после чего нам нужно добавить следующее подключение в файл config/queue.php
'rabbitmq' => [ 'driver' => 'rabbitmq', 'queue' => env('RABBITMQ_QUEUE', 'default'), 'connection' => PhpAmqpLib\Connection\AMQPLazyConnection::class, 'hosts' => [ [ 'host' => env('RABBITMQ_HOST', '127.0.0.1'), 'port' => env('RABBITMQ_PORT', 5672), 'user' => env('RABBITMQ_USER', 'guest'), 'password' => env('RABBITMQ_PASSWORD', 'guest'), 'vhost' => env('RABBITMQ_VHOST', '/'), ], ], 'options' => [ 'ssl_options' => [ 'cafile' => env('RABBITMQ_SSL_CAFILE', null), 'local_cert' => env('RABBITMQ_SSL_LOCALCERT', null), 'local_key' => env('RABBITMQ_SSL_LOCALKEY', null), 'verify_peer' => env('RABBITMQ_SSL_VERIFY_PEER', true), 'passphrase' => env('RABBITMQ_SSL_PASSPHRASE', null), ], ], /* * Set to "horizon" if you wish to use Laravel Horizon. */ 'worker' => env('RABBITMQ_WORKER', 'default'), ],
и затем нам нужно обновить файл .env
:
QUEUE_CONNECTION=rabbitmq RABBITMQ_DSN=amqp:// RABBITMQ_HOST=woodpecker.rmq.cloudamqp.com RABBITMQ_VHOST=ojydhdau RABBITMQ_USER=ojydhdau RABBITMQ_PASSWORD=Bctt-m_WhXrWdNGcb1L5D7D5j-3j-8Gc RABBITMQ_QUEUE=jobs
PS: переменная QUEUE_CONNECTION
уже есть в файле .env
, поэтому не создавайте еще одну, а обновите имеющуюся.
Перед тестированием новой конфигурации сделаем следующее:
Откроем менеджер RabbitMQ и проверим, есть ли у нас там очереди и задачи:
как видите, у нас пусто:
Прежде, чем отправлять новые запросы, нам нужно перезапустить наш локальный веб-сервер, чтобы применить изменения файла .env
.
И теперь, если вы отправите новый POST-запрос в приложение, то увидите следующее:
Когда мы переключимся на вкладку очередей, то увидим, что была создана новая очередь:
Обратите внимание, что состояние очереди idle
и как только мы выполним команду queue:work
, оно изменится на running
и задача будет обработана.
PS: при использовании RabbitMQ не нужно вручную проверять работают ли воркеры очереди. Всё, что вам нужно сделать, это проверить состояние очередей (если там idle
, то значит не работают).
Использование нескольких очередей
Теперь представьте, что вы развернули свое приложение и открыли его для всех. Еще одна задача, которую могут решить очереди, — отправка приветственных писем новым пользователям.
Одна из причин, по которой нужно передать это в очередь, заключается в том, что, скорее всего, вы будете использовать стороннюю службу для отправки электронных писем, и вы не хотите заставлять своих пользователей ждать редиректа в панель управления после регистрации, пока им не будут отправлены эти письма.
Процесс будет аналогичен обработке входящих POST-запросов. Каждый раз, когда мы хотим отправить новое электронное письмо, оно ставится в очередь, а затем обрабатывается в фоновом режиме.
На этом этапе вы заметите одну вещь: все задачи ставятся в одну и туже очередь под названием jobs
(помните, что у нас есть такая переменная RABBITMQ_QUEUE=jobs
в файле .env
).
Если мы не указываем название очереди, в которую хотим отправить задачу, то Laravel просто отправляет их в дефолтную очередь. Но мы можем отправлять каждый вид задач в свою определенную очередь.
// Эта задача будет отправлена в дефолтную очередь... Job::dispatch(); // Эта задача будет отправлена в очередь "emails"... Job::dispatch()->onQueue('emails');
Теперь, когда зарегистрируется новый пользователь — новая задача WelcomeEmail
будет отправлена в очередь emails
.
У нас есть два способа обработки задач:
1. либо мы открываем новую вкладку и запускаем команду queue:work
, а затем слушаем эту очередь:
php artisan queue:work –queue=emails
2. либо мы можем обслуживать обе очереди на одной вкладке, задавая приоритет каждой из них. Например, если мы хотим сначала обслужить все задачи в очереди jobs
, а потом обслужить почту, то мы можем выполнить следующее:
php artisan queue:work --queue=jobs,emails
PS: скорее всего, вам не нужно устанавливать приоритеты при развертывании приложения на продакшн-сервере, так как там каждая очередь будет обрабатываться в отдельном фоновом процессе.
Что дальше?
Если вы всё поняли, то теперь вы готовы развернуть приложение на своем продакшн-сервере.
В следующей статье мы рассмотрим, как можно запустить воркеры на удаленном сервере, ведь мы не можем постоянно держать открытой вкладку с терминалом, где запущена обработка задач.
Автор: Youghourta Benali
Перевод: Алексей Широков
Наш Телеграм-канал — следите за новостями о Laravel.