Руководство по Очередям и Задачам. Часть 2: Подключения и настройки

В этой статье мы расскажем об альтернативном подключении очередей и о том, как мы можем использовать несколько разных очередей для разных задач, а также, как можно расставлять приоритеты задач/очередей. Надеюсь, вы уже прочитали первую часть этой статьи.

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.