7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Code
  2. Laravel

Отложенные задачи в Laravel с помощью очередей

Scroll to top
Read Time: 12 mins

Russian (Pусский) translation by Masha Kolesnikova (you can also view the original English article)

В этой статье мы рассмотрим API очереди в фреймворке для  веб приложений Laravel. Оно позволяет откладывать ресурсоемкие задачи во время выполнения сценария, чтобы улучшить общий опыт использования нашего приложения для конечных пользователей. После базовой терминологии, я продемонстрирую ее, реализовав пример реального приложения.

Время загрузки страницы является важным аспектом любого успешного веб-сайта, и не следует упускать из виду важность этого, так как оно влияет на SEO сайта и итоговый опыт конечного пользователя. Чаще всего вам приходится отлаживать веб-страницы с длительным временем загрузки. Конечно, есть разные подходы, которые вы могли бы использовать для устранения этой проблемы.

При исследовании причин вы часто понимаете, что есть определенные блоки кода, вызывающие задержку в выполнении страницы. Следующее, что вы могли бы попробовать, это определить блоки, которые можно отложить для обработки и которые не оказывают реального влияния на конечный результат текущей страницы. Это должно действительно улучшить общую скорость отдачи веб-страницы, поскольку мы устранили блоки кода, которые вызывают задержку.

Сегодня мы рассмотрим аналогичную концепцию в контексте веб-фреймворка Laravel. Фактически, Laravel уже предоставляет полезный встроенный API, который позволяет нам отсрочить обработку задач - API очередей. Не тратя много времени, я расскажу об основных элементах API очередей.

Драйверы, соединения, очереди и задания

Основная цель API Queue - запускать задания, которые добавляются в очередь. Далее очередь может принадлежать определенному соединению, и это соединение может принадлежать определенному драйверу очереди, настроенному для работы с этим соединением. Давайте кратко попытаемся понять, что я только что сказал.

Драйверы очереди

Точно так же вы использовали бы другой драйвер для подключения к базе данных, вы также можете выбрать из множества разных драйверов очереди. API очереди поддерживает различные адаптеры, такие как база данных, beanstalkd, sqs и redis.

Драйвер очереди - это просто место, которое используется для хранения информации, связанной с  этой очередью. Например, если вы используете драйвер очереди баз данных, новое задание будет добавлено в таблицу заданий в базе данных. С другой стороны, если вы настроили redis в качестве драйвера очереди по умолчанию, задание будет добавлено на сервер redis.

API Queue также предоставляет два специальных драйвера очереди для тестирования - sync и null. Драйвер очереди синхронизации используется для немедленного выполнения задания на очередь, в то время как драйвер очереди null используется для пропуска задания, чтобы он не выполнялся вообще.

Соединение

Когда вы настраиваете API Queue в первый раз, вам нужно указать соединение по умолчанию, которое должно использоваться для обработки очереди по умолчанию. Как минимум, соединение должно предоставить следующую информацию:

  • драйвер очереди, который будет использоваться
  • конкретные значения конфигурации драйвера очереди
  • имя очереди по умолчанию, в которое будет добавлено задание

Очереди

Когда вы добавляете какое-либо задание в очередь, оно будет добавлено в очередь по умолчанию. Фактически, в большинстве случаев это то что нужно, если у вас нет рабочих мест, которым необходимо уделять более высокий приоритет по сравнению с другими заданиями. В этом случае вы можете создать очередь с именем high и разместить задания с более высоким приоритетом в этой конкретной очереди.

Когда вы запускаете воркера очереди, который обрабатывает задания в очереди, вы можете опционально передать параметр --queue, который позволяет вам указывать имена очередей в том порядке, в котором они должны быть обработаны. Например, если вы укажете, что --queue = high, default, он сначала обрабатывает задания в  очереди high, и как только оно будет завершено, он будет получать задания в очереди по умолчанию.

Задания

Задача в Queue API - это задача, отложенная из основного потока выполнения. Например, если вы хотите создать превью картинки, когда пользователь загружает изображение из внешнего интерфейса, вы можете создать новое задание, которое обрабатывает обработку эскизов. Таким образом, вы можете отложить задачу обработки эскизов из основного потока выполнения.

Это было базовое введение в терминологию Queue API. В следующем разделе мы рассмотрим, как создать собственное задание очереди и запустить его, используя Laravel.

Создайте свою первую работу в очереди

К настоящему времени вы должны уже чувствовать себя уверено в работе с очередью. В этом разделе мы собираемся реализовать пример реального приложения, демонстрирующий концепцию задач очереди в Laravel.

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

Сначала кажется, это разумный подход, если вы собираетесь создать пару версий, и это не займет слишком много времени. С другой стороны, если вы имеете дело с приложением, которое требует интенсивной обработки и, следовательно, потребляет больше ресурсов, обработка в режиме реального времени может закончиться неудовлетворенным пользователем.

Очевидным вариантом, который появляется в вашем сознании, в первую очередь, является отсрочить обработку генерации миниатюр как можно позже. Самый простой подход, который вы могли бы реализовать в этом конкретном сценарии, - установить задание cron, которое запускает обработку через равные промежутки времени, и это должно помочь.

С другой стороны, гораздо лучший подход состоит в том, чтобы отложить и перевести задачу в очередь, и позволить работнику очереди обрабатывать ее, когда у нее есть шанс сделать это. В рабочей среде работник очереди - это демон-скрипт, который всегда запускает и обрабатывает задачи в очереди. Очевидным преимуществом такого подхода является гораздо лучший опыт работы с конечным пользователем, и вам не нужно ждать выполнения cron, поскольку работа будет обработана как можно скорее.

Я думаю, что уже достаточно теории, чтобы перейти к реальной реализации.

В нашем случае мы будем использовать драйвер очереди database, и нам требуется создать таблицу jobs в базе данных. Таблица jobs содержит все задания, которые необходимо обработать в следующем запуске воркера очереди.

Прежде чем мы начнем и создадим таблицу jobs, давайте изменим конфигурацию очереди по умолчанию из sync в database в файле config/queue.php.

Фактически, Laravel уже предоставляет artisan команду, которая помогает нам создать таблицу jobs. Выполните следующую команду в корне вашего приложения Laravel и создайте необходимую миграцию базы данных, которая создаст таблицу jobs.

Файл миграции, созданный в database/migrations/YYYY_MM_DD_HHMMSS_create_jobs_table.php, должен выглядеть так:

Затем, давайте запустим команду migrate, чтобы она фактически создала таблицу jobs в базе данных.

Это касается миграции jobs.

Затем давайте создадим модель Image, которая будет использоваться для управления изображениями, загружаемыми конечным пользователем. Для модели Image также требуется связанная таблица базы данных, поэтому при создании модели изображения мы будем использовать параметр -migrate.

Вышеупомянутая команда должна создать класс модели Image и связанную с ним миграцию базы данных.

Класс модели Image должен выглядеть следующим образом:

И файл миграции базы данных должен быть создан в database/migrations/YYYY_MM_DD_HHMMSS_create_images_table.php. Мы также хотим сохранить исходный путь изображения, загруженного конечным пользователем. Давайте переработаем код файла миграции базы данных Image, чтобы он выглядел следующим образом.

Как вы можете видеть, мы добавили столбец $table->string('org_path'), чтобы сохранить путь к исходному изображению. Затем вам просто нужно запустить команду migrate, чтобы фактически создать эту таблицу в базе данных.

И это касается модели Image.

Затем давайте создадим фактическое задание очереди, которое отвечает за обработку эскизов изображений. Для обработки миниатюр мы собираемся использовать очень популярную библиотеку обработки изображений - Intervention Image.

Чтобы установить библиотеку Intervention Image, запустите следующую команду в корне вашего приложения.

Теперь пришло время создать класс Job, и для этого мы будем использовать команду artisan.

Это должно создать шаблон класса Job в app/Jobs/ProcessImageThumbnails.php. Давайте заменим содержимое этого файла следующим.

Когда работник очереди начинает обработку любого задания, он ищет метод handle. Таким образом, метод handle содержит основную логику вашей работы.

В нашем случае нам нужно создать миниатюру изображения, загруженного пользователем. Код метода handle довольно прост - мы извлекаем изображение из модели ImageModel и создаем эскиз, используя библиотеку Intervention Image. Конечно, нам нужно передать соответствующую модель Image, когда мы отправим наше задание, и мы увидим это через мгновение.

Чтобы протестировать наше вновь созданное задание, мы создадим простую форму загрузки, которая позволяет пользователю загружать изображение. Конечно, мы не будем создавать эскизы изображений сразу; мы отложим эту задачу так, чтобы ее можно было обработать работником очереди.

Давайте создадим файл контроллера в app/Http/Controllers/ImageController.php, как показано ниже.

Давайте создадим соответствующий файл отображения в resources/views/upload_form.blade.php.

Наконец, давайте добавим маршруты для действий index и upload в файле routes/web.php.

В контроллере ImageController метод index используется для отображения формы загрузки.

Когда пользователь отправляет форму, вызывается метод upload.

В начале метода upload вы увидите обычный код загрузки файлов, который перемещает загруженный файл в каталог public/images. Затем мы вставляем запись базы данных с использованием модели App/Image.

Наконец, мы используем задание ProcessImageThumbnails, чтобы отложить задачу обработки миниатюр. Важно отметить, что это метод dispatch используется для отложенной задачи. В конце пользователь перенаправляется на страницу загрузки с сообщением об успешном завершении.

На данный момент задание добавляется в таблицу jobs для обработки. Подтвердите это, выполнив следующий запрос.

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

Обработчик очереди

Задача работника очереди Laravel заключается в обработке заданий, стоящих в очереди для обработки. Фактически, есть команда artisan, которая помогает нам запустить работника очереди.

Как только вы запустите эту команду, он начнет обрабатывать ожидающие задания. В нашем случае он должен обработать задание ProcessImageThumbnails, которое было поставлено в очередь, когда пользователь загрузил изображение.

Вы заметили бы, что при запуске работника очереди он будет работать до тех пор, пока вы не убьете его вручную или не закроете терминал. Фактически, он ожидает, что следующее задание будет обработано. Как только в очереди будет новое задание, оно будет обработано сразу, если обработчик очереди запущен.

Конечно, мы не можем заставить его работать таким образом, поэтому нам нужно найти способ, чтобы обработчик очереди работал постоянно в фоновом режиме.

Для этого уже есть несколько инструментов управления процессом, из которых вы можете выбрать. Вот этот список:

  • Circus
  • daemontools
  • Monit
  • Supervisor
  • Upstart

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

Итак, это было API Queue на ваше рассмотрение. Вы можете использовать его в своей повседневной разработке, чтобы отложить трудоемкие задачи для улучшения работы конечного пользователя.

Заключение

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

Мы начали с базового введения в Queue API, который включал обсуждение соединений, очередей и заданий. Во второй половине статьи мы создали специальное задание очереди, которое продемонстрировало, как вы можете использовать API Queue в реальном приложении.

Для тех из вас, кто только начинает работать с Laravel или хочет расширить свои знания, сайт или приложение с расширениями, у нас есть множество вещей, которые вы можете еще изучить на Envato Market.

Не стесняйтесь использовать форму обратной связи ниже, чтобы оставить свои запросы и предложения.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.