php artisan queue work

Руководство по Очередям и Задачам. Часть 1: Создаем простое аналитическое приложение

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

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

Но однажды у меня в голове щелкнуло и мне всё стал ясно. Надеюсь с вами произойдет тоже самое и потом вы будете удивляться как все эти годы жили без них.

Замечу, что основная проблема с обучением по этой теме (в контексте Laravel) заключается не в новизне материала, а в том что большинство учебных материалов в интернете, либо слишком теоретические, либо работают с такими простыми примерами, что и не встретишь в реальном мире.

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

Описание приложения

Наше приложение (назовем его basic-analytics-v01 ) будет очень простым. Оно позволит нам отслеживать трафик нашего сайта.

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

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

basic-analytics-v01

Мы сделаем это приложение (по крайней мере, его первую версию) действительно простым.

Давайте сосредоточимся на хранении этих заходов в базе данных. Все, что нам нужно, это конечная точка и контроллер (да, поместим всё в контроллер).

Во-первых, давайте создадим две основные модели, которые нам понадобятся, и их соответствующие миграции.

Код нашего контроллера:

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

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

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

Время отклика

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

Когда я это проверяю, отправляя запрос локально с помощью Postman, то вот что получаю:

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

100 мс — это довольно долго, хотя мы в контроллере и не выполняем никакой существенной обработки. А представьте, что нам нужно выполнить дополнительные действия, плюс несколько запросов к базе данных или даже пообщаться со сторонним API. То есть мы заблокируем скрипт, отправляющий нам запрос (и возможно даже страницу, на которой выполняется этот скрипт), до тех пор пока мы не закончим обработку.

Количество одновременных запросов

Неважно, запускаете ли вы приложение локально или на продакшене, всегда существует лимит на количества запросов, которые вы можете обработать.

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

Потеря данных

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

Теперь посмотрим, как использование Задач и Очередей поможет нам решить все эти проблемы.

Отправка Задач в Очередь

Сначала поговорим о том, что такое Очереди и Задачи.

В двух словах, Задача — это кусок кода (например, метод), который мы хотим выполнить. И мы помещаем его в Очередь, чтобы отложить его выполнение и делегировать «чему-то другому».

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

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

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

Один из способов сделать это — поместить код, который мы хотим делегировать, в замыкание и отправить его в очередь следующим образом:

Но я рекомендую вам создать выделенный класс задач и затем отправить его вместо этого. Для создания такого класса нам нужно выполнить следующую команду:

Она сгенерирует следующий класс:

Но как передать аргументы (публичный ID трекера и сам запрос) в код отслеживания? А мы передадим их конструктору класса, а затем метод handle может использовать их следующим образом:

Теперь каждый раз при получении нового Hit, нам нужно отправлять новую Задачу.

Мы можем сделать это следующим образом:

Посмотрите, какой наш контроллер тонкий и чистый.

Что происходит? Мы действительно делегируем?

Подключение Очереди

это означает, что мы обрабатываем любые Задачи сразу после их отправки и делаем это синхронно.

Итак, если мы хотим получить выгоду от использования очередей, то нам нужно подключить их к чему-то другому. Другими словами, нам нужно место, куда мы можем «поставить в очередь»/сохранить задачи до их обработки.

Поскольку мы только начинаем работу с Очередями и Задачами, то давайте пока не трогать подключения требующие сторонних служб (beanstalkd и sqs), либо приложений, которых у нас может и не быть (redis). Остается database (база данных).

Таким образом, каждый раз, когда мы получаем новую Задачу, она будет сохраняться в базе данных (в специальной таблице). И потом уже оттуда она будет взята и обработана.

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

Она только создает миграцию и нам нужно выполнить миграцию этой таблицы.

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

Теперь, если мы отправим запрос POST еще раз, мы увидим следующее:

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

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

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

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

Если вам стало интересно, как запустить эту команду на продакшн-сервере и как оставить её работать после вашего логаута, то не беспокойтесь, об этом мы поговорим позже.

Параллельная обработка нескольких задач

После того, как вы увидели, что можно отправлять задачи и обрабатывать их асинхронно (т.е. нам не нужно ждать их завершения), давайте перейдем ко второй причине, по которой мы используем Задачи и Очереди: параллелизм.

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

Опять же, если вам интересно, как это сделать на продакшн-сервере, не беспокойтесь, мы рассмотрим это позже.

Работа с проваленными задачами (failed jobs)

А теперь представьте, что вы добавили на свой сервер новый код, который привел к ошибке. Прежде, чем вы её обнаружили прошло некоторое время, а это означает, что все запросы, полученные вашим приложением за этот период, просто не были обработаны. Есть ли способ их не потерять и обработать позже, после исправления вашей ошибки? Ведь нельзя просто попросить своего клиента повторно отправить вам свои запросы (это просто невозможно). К счастью, данные не теряются, и мы можем без проблем повторить попытку обработки проваленных задач.

Но прежде чем мы рассмотрим, как мы это сделать, давайте почитаем справку команды queue:work :

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

Обратите внимание, что команда может принимает несколько аргументов. Сейчас нас интересует аргумент tries

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

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

Теперь давайте остановим все процессы queue:work и попробуем сымитировать неудачную задачу.

Добавим следующую строку в начало метода handle() :

И обработка задачи будет каждый раз завершаться неудачно. Отправьте несколько новых POST-запросов и давайте посмотрим, что произойдет.

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

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

Теперь давайте уберем строку с исключением, и попробуем снова выполнить эти задачи.

Мы можем повторить попытку обработать все проваленные задачи или выбрать одну конкретную вот таким вот образом (замените all идентификатором задачи):

Если вы не остановили предыдущий процесс queue:work перед повторной попыткой выполнения задач, вы увидите, что повторные попытки снова завершились неудачно. Почему так происходит?

Согласно документации Laravel :

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

Соответственно, мы должны перезапустить этот процесс.

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

Но, согласно официальной документации, эта команда не такая эффективная, как queue:work :

Теперь давайте снова запустим процесс queue:work и повторим все проваленные задачи.

Что дальше

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

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

Наш php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue workТелеграм-канал — следите за новостями о Laravel.

Задать вопросы по урокам можно на нашем форуме.

Источник

Laravel Framework Russian Community

Настройка

В Laravel компонент Queue предоставляет единое API для различных сервисов очередей. Очереди позволяют вам отложить выполнение времязатратной задачи, такой как отправка e-mail, на более позднее время, таким образом на порядок ускоряя загрузку (генерацию) страницы.

Создание таблицы очереди

Установка пакетов

Упомянутые выше драйвера имеют следующие зависимости:

Использование очередей

Добавление новой задачи в очередь

Чтобы добавить команду в очередь, воспользуйтесь методом push :

Добавление задачи в определенную очередь

У приложения может быть несколько очередей. Можно поместить команду в определенную очередь:

Передача данных нескольким задачам сразу

Если вам надо передать одни и те же данные нескольким задачам в очереди, вы можете использовать метод Queue::bulk :

Отложенное выполнение задачи

Иногда вам нужно, чтобы задача начала исполняться не сразу после занесения её в очередь, а спустя какое-то время. Например, выслать пользователю письмо спустя 15 минут после регистрации. Для этого существует метод Queue::later :

Очереди и модели Eloquent

Если ваша команда, которая отправляется в очередь, принимает модель Eloquent в своём конструкторе, в очередь будет передан только её ID. Когда команда выполняется обработчиком очереди (вызывается метод handle ), фреймворк автоматически загружает из базы данных экземпляр модели с данным ID. Это происходит полностью прозрачно для приложения.

Удаление выполненной задачи

Когда команда успешно заканчивает выполнение, т.е. в процессе её работы не было брошено ни одно непойманное исключение, она автоматически удаляется из очереди.

Помещение команды обратно в очередь

Получение числа попыток запуска

Вы можете узнать, сколько попыток перезапуска команды уже было:

Примечание: Вы должны включить в класс трейт Illuminate\Queue\InteractsWithQueue чтобы использовать этот метод.

Добавление функций-замыканий в очередь

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

Добавить функцию-замыкание в очередь

При использовании push-очередей Iron.io, будьте особенно внимательны при добавлении замыканий. Конечная точка выполнения, получающая ваше сообщение из очереди, должна проверить входящую последовательность-ключ, чтобы удостовериться, что запрос действительно исходит от Iron.io. Например, ваша конечная push-точка может иметь адрес вида https://yourapp.com/queue/receive?token=SecretToken где значение token можно проверять перед собственно обработкой задачи.

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

Задачи, помещенные в очередь должен кто-то исполнять. Laravel включает в себя Artisan-задачу, которая раз в несколько секунд опрашивает очередь и, если в очереди есть задача, запускает в отдельном процессе рабочего (worker), который выполняет её. Задачи запускаются не параллельно, а последовательно. Вы можете запустить её командой queue:listen :

Запуск сервера выполнения задач

Вы также можете указать, какое именно соединение должно прослушиваться:

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

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

Указание числа секунд для работы сервера

Вы можете установить интервал в секундах между запусками задач

Уменьшение частоты опроса очереди

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

Если очередь пуста, она будет опрашиваться раз в 5 секунд. Если в очереди есть задачи, они исполняются без задержек.

Обработка только первой задачи в очереди

Для обработки только одной (первой) задачи можно использовать команду queue:work :

Обработчик очереди в режиме демона

Запустить обработчика очереди в демон-режиме:

Деплой приложения с обработчиком-демоном

Чтобы рестартовать обработчиков очереди, воспользуйтесь командой queue:restart

Эта команда заставит всех обработчиков-демонов перезапуститься после завершения выполнения их текущей задачи.

Программирование задач с учетом обработчиков-демонов

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

Push-очереди

Регистрация подписчика push-очереди

После этого вы можете использовать команду queue:subscribe Artisan для регистрации URL точки (end-point), которая будет получать добавляемые в очередь задачи.

Теперь, когда вы войдёте в ваш профиль Iron, то увидите новую push-очередь и её URL подписки. Вы можете подписать любое число URL на одну очередь. Дальше создайте маршрут для вашей точки queue/receive и пусть он возвращает результат вызова метода Queue::marshal :

Незавершённые задачи

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

Данная команда создает миграцию для создания таблицы в вашей базе данных:

Получение незавершённых задач

Список всех незавершённых задач c их ID вам покажет команда queue:failed :

Вы можете вручную рестартовать задачу по её ID:

Если вы хотите удалить задачу из списка незавершённых, используйте queue:forget :

Чтобы очистить весь список незавершённых задач, используйте queue:flush :

Источник

Laravel Framework Russian Community

Настройка

В Laravel компонент Queue предоставляет единое API для различных сервисов очередей. Очереди позволяют вам отложить выполнение времязатратной задачи, такой как отправка e-mail, на более позднее время, таким образом на порядок ускоряя загрузку (генерацию) страницы.

Создание таблицы очереди

Установка пакетов

Упомянутые выше драйвера имеют следующие зависимости:

Использование очередей

Добавление новой задачи в очередь

Чтобы добавить команду в очередь, воспользуйтесь методом push :

Добавление задачи в определенную очередь

У приложения может быть несколько очередей. Можно поместить команду в определенную очередь:

Передача данных нескольким задачам сразу

Если вам надо передать одни и те же данные нескольким задачам в очереди, вы можете использовать метод Queue::bulk :

Отложенное выполнение задачи

Иногда вам нужно, чтобы задача начала исполняться не сразу после занесения её в очередь, а спустя какое-то время. Например, выслать пользователю письмо спустя 15 минут после регистрации. Для этого существует метод Queue::later :

Очереди и модели Eloquent

Если ваша команда, которая отправляется в очередь, принимает модель Eloquent в своём конструкторе, в очередь будет передан только её ID. Когда команда выполняется обработчиком очереди (вызывается метод handle ), фреймворк автоматически загружает из базы данных экземпляр модели с данным ID. Это происходит полностью прозрачно для приложения.

Удаление выполненной задачи

Когда команда успешно заканчивает выполнение, т.е. в процессе её работы не было брошено ни одно непойманное исключение, она автоматически удаляется из очереди.

Помещение команды обратно в очередь

Получение числа попыток запуска

Вы можете узнать, сколько попыток перезапуска команды уже было:

Примечание: Вы должны включить в класс трейт Illuminate\Queue\InteractsWithQueue чтобы использовать этот метод.

Добавление функций-замыканий в очередь

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

Добавить функцию-замыкание в очередь

При использовании push-очередей Iron.io, будьте особенно внимательны при добавлении замыканий. Конечная точка выполнения, получающая ваше сообщение из очереди, должна проверить входящую последовательность-ключ, чтобы удостовериться, что запрос действительно исходит от Iron.io. Например, ваша конечная push-точка может иметь адрес вида https://yourapp.com/queue/receive?token=SecretToken где значение token можно проверять перед собственно обработкой задачи.

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

Задачи, помещенные в очередь должен кто-то исполнять. Laravel включает в себя Artisan-задачу, которая раз в несколько секунд опрашивает очередь и, если в очереди есть задача, запускает в отдельном процессе рабочего (worker), который выполняет её. Задачи запускаются не параллельно, а последовательно. Вы можете запустить её командой queue:listen :

Запуск сервера выполнения задач

Вы также можете указать, какое именно соединение должно прослушиваться:

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

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

Указание числа секунд для работы сервера

Уменьшение частоты опроса очереди

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

Если очередь пуста, она будет опрашиваться раз в 5 секунд. Если в очереди есть задачи, они исполняются без задержек.

Обработка только первой задачи в очереди

Для обработки только одной (первой) задачи можно использовать команду queue:work :

Обработчик очереди в режиме демона

Запустить обработчика очереди в демон-режиме:

Деплой приложения с обработчиком-демоном

Чтобы рестартовать обработчиков очереди, воспользуйтесь командой queue:restart

Эта команда заставит всех обработчиков-демонов перезапуститься после завершения выполнения их текущей задачи.

Программирование задач с учетом обработчиков-демонов

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

Push-очереди

Регистрация подписчика push-очереди

После этого вы можете использовать команду queue:subscribe Artisan для регистрации URL точки (end-point), которая будет получать добавляемые в очередь задачи.

Теперь, когда вы войдёте в ваш профиль Iron, то увидите новую push-очередь и её URL подписки. Вы можете подписать любое число URL на одну очередь. Дальше создайте маршрут для вашей точки queue/receive и пусть он возвращает результат вызова метода Queue::marshal :

Незавершённые задачи

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

Данная команда создает миграцию для создания таблицы в вашей базе данных:

Получение незавершённых задач

Список всех незавершённых задач c их ID вам покажет команда queue:failed :

Вы можете вручную рестартовать задачу по её ID:

Если вы хотите удалить задачу из списка незавершённых, используйте queue:forget :

Чтобы очистить весь список незавершённых задач, используйте queue:flush :

Источник

Делаем наш продукт готовым к масштабированию с помощью очередей Laravel

Перевод статьи подготовлен специально для студентов курса «Framework Laravel».

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

Привет, я Валерио, инженер-программист из Италии.

Это руководство предназначено для всех PHP разработчиков, уже имеющих онлайн-приложения с реальными пользователями, но которым недостает более глубокого понимания того, как внедрить (или значительно улучшить) масштабируемость в своей системе, используя очереди Laravel. Впервые я узнал о Laravel в конце 2013 года на старте 5-й версии фреймворка. Тогда я еще не был разработчиком, вовлеченным в серьезные проекты, и одним из аспектов современных фреймворков, особенно в Laravel, который казался мне самым непостижимым, были очереди (Queues).

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

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

В этой статье я собираюсь рассказать вам, как я открыл для себя очереди (queues) и задачи (jobs), и какие конфигурации помогли мне обрабатывать большие объемы данных в режиме реального времени, сохраняя при этом экономию ресурсов сервера.

Введение

Когда PHP приложение получает входящий http-запрос, наш код выполняется последовательно шаг за шагом, пока выполнение запроса не закончится и клиенту (например, браузеру пользователя) не будет возвращен ответ. Это синхронное поведение действительно интуитивно, предсказуемо и просто для понимания. Я отправляю http-запрос на эндпоинт, приложение извлекает данные из базы данных, преобразует их в соответствующий формат, выполняет некоторые дополнительные задачи и отправляет их обратно. Все происходит линейно.

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

Чем больше приложение разрастается, тем хуже становится эта проблема.

Что такое задача?

Задача (Job) — это класс, который реализует метод «handle», содержащий логику, которую мы хотим выполнять асинхронно.

Как упомянуто выше, основная причина заключения части кода в Job — выполнить трудоемкую задачу, не заставляя пользователя дожидаться ее выполнения.

Что мы имеем в виду под «трудоемкими задачами»?

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

Как для владельца продукта, для меня очень важно синхронизировать информацию о поездках пользователей с нашими инструментами маркетинга и поддержки клиентов. Таким образом, основываясь на действиях пользователей, мы обновляем информацию о пользователях в различном внешнем ПО через API (или внешние http вызовы) в целях сервиса и маркетинга.
Один из наиболее часто используемых эндпоинтов в моем приложении может отправить 10 электронных писем и выполнить 3 http-вызова ко внешним службам до завершения. Ни один пользователь не будет ждать столько времени — скорее всего, они все попросту перестанут использовать мое приложение.

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

Мне не нужно ждать завершения всех этих процессов, прежде чем возвращать ответ; напротив, ожидание будет равно времени, необходимому для публикации их в очереди. А это означает разницу между 10 секундами и 10 миллисекундами.

Кто выполняет эти задачи после отправки их в очередь?

Это классическая архитектура «publisher/consumer». Мы уже опубликовали наши задачи в очереди из контроллера, теперь же мы собираемся понять, как используется очередь, и, наконец, выполняются задачи.

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

Чтобы использовать очередь, нам нужно запустить одну из самых популярных artisan команд:

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

Замечательно! Laravel предоставляет готовый интерфейс для помещения задач в очередь и готовую к использованию команду для извлечения задач из очереди и выполнения их кода в фоновом режиме.

Роль Supervisor

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

Если задача терпит неудачу во время выбрасывания исключения, команда queue:work прекратит свою работу.

Для того чтобы процесс queue:work работал постоянно (потребляя ваши очереди), вы должны использовать монитор процессов, такой как Supervisor, чтобы гарантировать, что команда queue:work не прекращает работу, даже если задача вызывает исключение.Supervisor перезапускает команду после того, как она выходит из строя, начиная снова со следующей задачи, отставив вызвавшую исключение.

Задачи будут выполняться в фоновом режиме на вашем сервере, больше не имея зависимости от HTTP-запроса. Это вводит некоторые изменения, которые я должен был учитывать при реализации кода задачи.

Вот самые важные, на которые я обращу внимание:

Как я могу узнать, что код задачи не работает?

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

Подумайте об интеграции инструмента мониторинга в режиме реального времени, такого как Inspector, чтобы выводить на поверхность каждый недостаток.

У вас нет http-запроса

Http-запроса больше нет. Ваш код будет выполнен из cli.

Если вам нужны параметры запроса для выполнения ваших задач, вам нужно передать их в конструктор задачи для последующего использования во время выполнения:

Вы не знаете, кто вошел в систему

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

Понять, как масштабировать

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

Очереди представляют собой буферы FIFO («первым вошел — первым вышел»). Если вы запланировали много задач, возможно даже разных типов, им нужно ждать, пока другие справятся со своими задания, прежде чем завершиться.

Есть два способа масштабирования:

Несколько потребителей на очередь

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

Таким образом, пять задач будут извлечены из очереди за раз, ускоряя обработку очереди.

Очереди специального назначения

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

php artisan queue work. Смотреть фото php artisan queue work. Смотреть картинку php artisan queue work. Картинка про php artisan queue work. Фото php artisan queue work

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

Horizon

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

Запуск происходит посредством php artisan horizon вместо php artisan queue:work. Эта команда сканирует ваш файл конфигурации horizon.php и запускает ряд воркеров очереди в зависимости от конфигурации:

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

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

Моя собственная конфигурация

Inspector использует в основном три очереди:

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

Заключительные замечания

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *