Рубрики
Uncategorized

Надежная обработка заданий в очереди в Craft CMS

Прочная обработка заданий в очереди в CRAFT CMS CRAFT CMS использует задания очереди для долгосрочных … Теги от CraftCMS, DEVOPS, очереди.

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

Эндрю Уэлч/ nystudio107.

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

Craft CMS Также использует очередь тоже. Любая длительная задача упакована в работа И рабочие места введены в очередь быть выполненным в порядке.

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

Вот несколько длительных задач, которые в конечном итоге в качестве рабочих мест в очереди Craft CMS:

  • Обновление входных проектов и ревизий
  • Удаление устаревших шаблонов кэши
  • Генерация ожидающих образах преобразований
  • Восстановление элементов
  • Обновление поисковых индексов
  • Плагин создал задания очереди

Очередь существует, чтобы позволить этим часто длинным заданиям работать на заднем плане, не блокируя доступ к панели управления CRAFT CMS (CP), когда они выполняются.

Посмотрите, как они бегут

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

Учитывая, что Craft CMS построен на вершине Yii2 Framework это имеет смысл, что он использует существующие Yii2-queue Насложнил QueueInterface Сверху.

Это делает это так, чтобы он мог предоставить хороший дружественный статус UI в CP. Настройка ремесла по умолчанию использует драйвер базы данных (DB) для заданий в очереди, сохраняя их в очередь Таблица.

Хотя есть другие Драйверы очереди Доступно, вы вряд ли увидите любые выгоды от использования чего-либо, кроме драйвера CMS CMS DB. И вы потеряете вышеупомянутый статус UI в CP.

Но как заканчивается задания очереди? Вот как:

  • Когда кто-то доступа к CP
  • Через веб-запрос

Здесь лежит RUB с реализацией очереди по умолчанию в CRAFT CMS. Никакие задания очередей не будут работать вообще, если кто-то не входит в систему в CP и даже тогда они запускаются через веб-запрос.

Вот выдержка из Craft CMS CP.JS JavaScript, который выступает на веб-друга в Интернете:

runQueue: function() {
    if (!this.enableQueue) {
        return;
    }

    if (Craft.runQueueAutomatically) {
        Craft.queueActionRequest('queue/run', $.proxy(function(response, textStatus) {
            if (textStatus === 'success') {
                this.trackJobProgress(false, true);
            }
        }, this));
    }
    else {
        this.trackJobProgress(false, true);
    }
},

И вот Метод контроллера очереди/пробега Это заканчивается выполнением через AJAX:

/**
 * Runs any waiting jobs.
 *
 * @return Response
 */
public function actionRun(): Response
{
    // Prep the response
    $response = Craft::$app->getResponse();
    $response->content = '1';
    // Make sure Craft is configured to run queues over the web
    if (!Craft::$app->getConfig()->getGeneral()->runQueueAutomatically) {
        return $response;
    }
    // Make sure the queue isn't already running, and there are waiting jobs
    $queue = Craft::$app->getQueue();
    if ($queue->getHasReservedJobs() || !$queue->getHasWaitingJobs()) {
        return $response;
    }
    // Attempt to close the connection if this is an Ajax request
    if (Craft::$app->getRequest()->getIsAjax()) {
        $response->sendAndClose();
    }
    // Run the queue
    App::maxPowerCaptain();
    $queue->run();
    return $response;
}

Они делают то, что могут убедиться, что веб-задания очереди будут плавно работать, но есть только так много, что можно сделать. Брэндон Келли из пикселей и тоник даже отметил «Craft 2 и Craft3 по умолчанию, в основном, есть очередь бедняки» Отказ

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

Это может привести к плохим происходящим:

  • Очередь рабочие места составляют до тех пор, пока кто-то не входит в систему в CP
  • Джобс очереди может потерпеть неудачу или застрять, если они берут слишком долго и время
  • Джобс очереди может потерпеть неудачу или застрять, если у них закончится память
  • Длина задания очереди может повлиять на производительность CP или Frontend, когда они работают

К счастью, мы можем облегчить все эти проблемы, и не сложно делать!

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

Решения для работы очереди

К счастью, Yii2, и по расширению Craft CMS, поставляется с надежным набором инструментов командной строки, которые я детализирующую в исследуемой статье интерфейса командной строки CMS CMS CMS 3.

очередь Команда дает нам возможность перемещать нашу задания очереди в высокую передачу, запустив их напрямую. PHP код, запущенный через интерфейс командной строки консоли (CLI), использует отдельный php.ini файл, чем веб-ориентированный PHP-FPM Отказ Вот пример с моего сервера:

/etc/php/7.1/fpm/php.ini
/etc/php/7.1/cli/php.ini

Причина, по которой это важно, это что во время веб-сайтов PHP-FPM может иметь разумные настройки для Memory_ Limit и max_ execution_ время PHP на основе CLI обычно не имеет memory_limit и нет max_execution_time. .

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

Так что запуск нашей задании очереди через PHP CLI дает нам следующие преимущества:

  • Может быть запущен в любое время, а не только когда кто-то обращается к CP
  • Не будет прекращено из-за длительное время выполнения
  • Вряд ли выберется из памяти

Команды, которые мы используем Console Console:

  • Очередь/запустить — управляет всеми заданиями в очереди, затем выходит
  • очередь/слушать — Вечно управляет процессом, который слушает новых рабочих мест, добавленных в очередь и запускает их

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

Решение № 1: плагин Async очередь

Если вы хотите без суеты, нет решения Muss, который просто включает в себя устанавливать плагин, проверить Oliver Старк Плагин async очередь. Из описания плагина:

[Плагин Async очередь] заменяет обработчик очереди по умолчанию ремесла и перемещает выполнение очереди в неблокирующий фоновый процесс. Командный ремесло очередь/пробег выполняется сразу после того, как вы нажимаете работу в очередь.

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

Вот и все, ты закончил!

Решение № 2: Forge Daemons

Если вы используете замечательный Larave Forge для обеспечения ваших серверов (подробно обсуждается в Как агенции и фрилансеры должны делать веб-хостинг Статья), Forge предоставляет хороший интерфейс GUI для того, что он называет Демоны Отказ

Перейдите на свой сервер, затем нажмите на Daemons, и вы увидите графический интерфейс, который выглядит так:

Вот команда, которую мы добавили для Dev Mode .fm Веб-сайт:

/usr/bin/nice -n 10 /usr/bin/php /home/forge/devmode.fm/craft queue/listen --verbose

Давайте сломаем это:

  • /usr/bin/nice -n 10 — Это использует Unix Ницца команда для запуска процесса с использованием более низкого приоритета, поэтому он не будет вмешиваться в CP или внешний интерфейс
  • /usr/bin/php/home/forge/devmode.fm/craft queue/Слушайте --вербозу — Это начинает процесс PHP CLI для прослушивания каких-либо заданий в очереди и запустить их

Вы должны поменяться на свой путь к Ремесло CLI исполняемый; Наша есть /home/forge/devmode.fm/craft.

Мы говорим, что мы хотим запустить это как пользователь кузница И мы хотим 2 Из этих процессов работает. Нажмите Начать демон И вы будете приветствовать:

Затем убедитесь, что вы установили Runceueuatomatically Craft CMS general.php Настройка конфигурации к ложь Для вашего жить Производственная среда:

    // Live (production) environment
    'live' => [
        // Craft defined config settings
        'runQueueAutomatically' => false,
    ],

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

Вот и все, ты закончил!

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

Какие демоны вызов Forge на самом деле выполняются через Руководитель команда. Когда мы создали вышеупомянутый демон в GUI FORGE, он создал файл в /etc/supervisor/Conf.d :

forge@nys-production /etc/supervisor/conf.d $ ls -al
-rw-r--r-- 1 root root 293 Aug 3 14:55 daemon-157557.conf

Содержимое файла выглядит так:

[program:daemon-157557]
command=/usr/bin/nice -n 10 /usr/bin/php /home/forge/devmode.fm/craft queue/listen --verbose

process_name=%(program_name)s_%(process_num)02d
autostart=true
autorestart=true
user=forge
numprocs=2
redirect_stderr=true
stdout_logfile=/home/forge/.forge/daemon-157557.log

И действительно, это именно один из методов, рекомендованных в I в Yii2 работник запускающий контроль Статья. Хуцца!

Решение № 3 с использованием Heroku

Если вы используете Heroku Для ваших нужных потребностей вы можете использовать Работник Dynos Чтобы запустить ваш очередь/слушать команда:

./craft queue/listen --verbose

Затем убедитесь, что вы установили Runceueuatomatically Craft CMS general.php Настройка конфигурации к ложь Для вашего жить Производственная среда:

    // Live (production) environment
    'live' => [
        // Craft defined config settings
        'runQueueAutomatically' => false,
    ],

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

Вот и все, ты закончил!

Решение № 4: Использование SystemD

Если вы используете сервер Linux, но вы не используете Forge или Heroku, или, возможно, вы просто хотите настроить вещи самостоятельно, мы можем выполнить одно и то же, используя Systemd Отказ

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

Вот что я сделал для Dev Mode .fm использовать Systemd Чтобы запустить нашу очередь. Вам понадобится Sudo Доступ, чтобы иметь возможность сделать это, но, к счастью, большинство современных услуг хостинга VPS дают вам эту способность.

Сначала я создал .service Файл в /etc/systemd/system/ назван devmode-queue @ .service с помощью:

forge@nys-production ~ $ sudo nano /etc/systemd/system/devmode-queue@.service

Вот что выглядит содержимое файла:

[Unit]
Description=devMode.fm Queue Worker %I
After=network.target
After=mysql.service
Requires=mysql.service

[Service]
User=forge
Group=forge
ExecStart=/usr/bin/nice -n 10 /usr/bin/php /home/forge/devmode.fm/craft queue/listen --verbose
Restart=always

[Install]
WantedBy=multi-user.target

Давайте сломаем это:

  • /usr/bin/nice -n 10 — Это использует Unix Ницца команда для запуска процесса с использованием более низкого приоритета, поэтому он не будет вмешиваться в CP или внешний интерфейс
  • /usr/bin/php/home/forge/devmode.fm/craft queue/Слушайте --вербозу — Это начинает процесс PHP CLI для прослушивания каких-либо заданий в очереди и запустить их

Вы должны поменяться на свой путь к Ремесло CLI исполняемый; Наша есть /home/forge/devmode.fm/craft.

Мы говорим, что мы хотим запустить это как пользователь кузница Мы хотим, чтобы это перезапустить процесс отказа и что это зависит от обоих сеть и MySQL Услуги доступны.

Странный @ в .service Имя файла позволяет нам иметь несколько экземпляров этой службы. Затем мы можем использовать синтаксис диапазона {1..2} Чтобы указать, сколько из этих процессов мы хотим.

Мы создали файл, но нам нужно начать службу через:

forge@nys-production ~ $ sudo systemctl start devmode-queue@{1..2}

А затем, как и наши другие услуги, такие как nginx и mysqld. Мы хотим, чтобы он запустился автоматически, когда перезагрузим наш сервер:

forge@nys-production ~ $ sudo systemctl enable devmode-queue@{1..2}

Затем убедитесь, что вы установили Runceueuatomatically Craft CMS general.php Настройка конфигурации к ложь Для вашего жить Производственная среда:

    // Live (production) environment
    'live' => [
        // Craft defined config settings
        'runQueueAutomatically' => false,
    ],

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

Вот и все, ты закончил!

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

forge@nys-production ~ $ sudo journalctl -f -u devmode-queue@*.service
-- Logs begin at Sat 2019-08-03 13:23:17 EDT. --
Aug 03 14:06:04 nys-production nice[1364]: Processing element 42/47 - Neutrino: How I Learned to Stop Worrying and Love Webpack
Aug 03 14:06:04 nys-production nice[1364]: Processing element 43/47 - Google AMP: The Battle for the Internet's Soul?
Aug 03 14:06:04 nys-production nice[1364]: Processing element 44/47 - The Web of Future Past with John Allsopp
Aug 03 14:06:04 nys-production nice[1364]: Processing element 45/47 - Web Hosting with ArcusTech's Nevin Lyne
Aug 03 14:06:04 nys-production nice[1364]: Processing element 46/47 - Tailwind CSS utility-first CSS with Adam Wathan
Aug 03 14:06:04 nys-production nice[1364]: Processing element 47/47 - Talking Craft CMS 3 RC1!
Aug 03 14:06:04 nys-production nice[1364]: 2019-08-03 14:06:04 [1427] Generating episodes sitemap (attempt: 1) - Done (1.377 s)
Aug 04 09:25:25 nys-production nice[1364]: 2019-08-04 09:25:25 [1429] Generating calendar sitemap (attempt: 1) - Started
Aug 04 09:25:25 nys-production nice[1364]: Processing element 1/1 - Calendar of Upcoming Episodes
Aug 04 09:25:25 nys-production nice[1364]: 2019-08-04 09:25:25 [1429] Generating calendar sitemap (attempt: 1) - Done (0.174 s)

Вышеуказанная команда будет хвост Systemd Журналы, показывая только сообщения из нашего Devmode-queue услуга.

Вы можете узнать больше об использовании routeCttl в Как использовать LoogeCtl для просмотра и манипулирования системой Logs статья.

Добиться Дотано

Это совершенно необязательный раздел, который вы можете пропустить, если вы не заинтересованы в изучении того, как не использовать .env Файлы в производстве, как рекомендовано phpdotenv Авторы пакета:

PHPDOTENV изготовлен для среды развития, и, как правило, не следует использовать в производстве. В производстве фактические переменные среды должны быть установлены, так что нет нагрузки загрузки файла .env на каждый запрос. Это может быть достигнуто через автоматический процесс развертывания с инструментами, такими как бродячий, шеф-повар или кукольный, или может быть установлен вручную с облачными хозяевами, такими как pagodabox и heroku.

Кроме того, некоторые настройки имеют экологические переменные, введенные альтернативными средствами. Я сделал Dotenvy пакет, который облегчает генерацию .env.env. Пары из ключа/Value Parable как Apache, NGINX и Equivalents.

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

Все, что нам нужно сделать, это изменить нашу команду на это:

/bin/bash -c ". /home/forge/devmode.fm/.env_cli.txt && /usr/bin/nice -n 10 /usr/bin/php /home/forge/devmode.fm/craft queue/listen --verbose"

Все, что мы делаем, выполняет .env_cli.txt файл (созданный dotenvy ), который содержит наши экологические переменные, которые мы Экспорт в среду оболочки:

forge@nys-production ~/devmode.fm (master) $ cat .env_cli.txt
# CLI (bash) .env variables
# Paste these inside your .bashrc file in your $HOME directory:
export ENVIRONMENT="live"
export SECURITY_KEY="XXXXX"
export DB_DRIVER="pgsql"
export DB_SERVER="localhost"
export DB_USER="devmode"
export DB_PASSWORD="XXXXX"
export DB_DATABASE="devmode"
export DB_SCHEMA="public"
export DB_TABLE_PREFIX=""
export DB_PORT="5432"
export SITE_URL="https://devmode.fm/"
export BASE_PATH="/home/forge/devmode.fm/web/"
export BASE_URL="https://devmode.fm/"
export REDIS_HOSTNAME="localhost"
export REDIS_PORT="6379"
export REDIS_DEFAULT_DB="0"
export REDIS_CRAFT_DB="3"
export PUBLIC_PATH="/dist/"
export DEVSERVER_PUBLIC="http://192.168.10.10:8080"
export DEVSERVER_HOST="0.0.0.0"
export DEVSERVER_POLL="1"
export DEVSERVER_PORT="8080"
export DEVSERVER_HTTPS="0"

Остальное то же самое, что и команды, которые мы обсуждали выше для работы очередь/слушать , а потом мы обнимаем все это в /bin/sh -c Итак, оно появляется как одна команда, которая может быть выполнена.

Глубоко очередно

Вот некоторые вакансии очереди, которые вы можете найти интересную.

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

На самом деле есть случай, когда задания очереди можно запускать через нагрузку на страницу Frontend. Если у вас есть generateTransformsbeforepageload Установить на ложь (что по умолчанию), и есть ожидающие преобразования, которые необходимо создать.

Что происходит, это Активы:: getasseturl () Метод нажимает задание очереди преобразования изображения, которое вызывает Queue:: push () :

    /**
     * @inheritdoc
     */
    public function push($job)
    {
        // Capture the description so pushMessage() can access it
        if ($job instanceof JobInterface) {
            $this->_jobDescription = $job->getDescription();
        } else {
            $this->_jobDescription = null;
        }

        if (($id = parent::push($job)) === null) {
            return null;
        }

        // Have the response kick off a new queue runner if this is a site request
        if (Craft::$app->getConfig()->getGeneral()->runQueueAutomatically && !$this->_listeningForResponse) {
            $request = Craft::$app->getRequest();
            if ($request->getIsSiteRequest() && !$request->getIsAjax()) {
                Craft::$app->getResponse()->on(Response::EVENT_AFTER_PREPARE, [$this, 'handleResponse']);
                $this->_listeningForResponse = true;
            }
        }

        return $id;
    }

Так что, если это запрос сайта (Frontend), и это не запрос AJAX, Craft добавит звонок на Queue:: Handleresponse () который уволен, когда Ответ собирается быть отправлен обратно клиенту.

В этом случае Craft будет вводить какой-то JavaScript в запросе на интерфейс, который закрепляет Очередь/запустить Контроллер через AJAX:

    /**
     * Figure out how to initiate a new worker.
     */
    public function handleResponse()
    {
        // Prevent this from getting called twice
        $response = Craft::$app->getResponse();
        $response->off(Response::EVENT_AFTER_PREPARE, [$this, 'handleResponse']);

        // Ignore if any jobs are currently reserved
        if ($this->getHasReservedJobs()) {
            return;
        }

        // Ignore if this isn't an HTML/XHTML response
        if (!in_array($response->getContentType(), ['text/html', 'application/xhtml+xml'], true)) {
            return;
        }

        // Include JS that tells the browser to fire an Ajax request to kick off a new queue runner
        // (Ajax request code adapted from http://www.quirksmode.org/js/xmlhttp.html - thanks ppk!)
        $url = Json::encode(UrlHelper::actionUrl('queue/run'));
        $js = <<
/*

Хотя технически это может произойти для любой работы очереди, которая является Очередь:: толкнул () D В очереди во время запроса на интерфейс преобразования активов являются единственным случаем, я знаю, что это происходит на практике.

По этой причине, если вы публикуете любые запросы XHR для контроллеров ремесел или конечных точек API, убедитесь, что вы добавляете заголовок:

'X-Requested-With': 'XMLHttpRequest'

Ремесло ищет этот заголовок, чтобы определить, является ли запрос AJAX или нет, и не попытается прикрепить свой javaScript javaScript его javaScript к очереди к запросу, если запрос ajax.

Этот заголовок устанавливается автоматически jQuery для $ .ajax. () Запросы, но он не устанавливается автоматически популярными библиотеками, такими как Axios. .

Упаковка

Так какой метод я использую? Если я раскручиваю VPS с кузницей (который я обычно утра), то я буду использовать Решение № 2: Forge Daemons . Если это не кузнец, но у меня есть Sudo Доступ, тогда я буду использовать Решение № 3: Использование SystemD Отказ

Я использую Решение № 1: плагин Async очередь На клиентских сайтах, где ни один из вышеперечисленных не имеет смысла. Плагин Оливера великолепен, и намного лучше, чем путь по умолчанию, который выполняется задания очереди, но я люблю использовать существующие системы, если это возможно, и имея Хороший Контроль над приоритетом процесса, ну, приятно.

Замена по умолчанию веб-система задания очереди по умолчанию в CRAFT CMS с более надежной системой CLI на основе CLI будет платить дивиденды.

Ваша задания очереди будет работать более гладко, не сработает реже и оказывает меньшее влияние на CP/Frestend.

Это стоит того. Сделай это.

Счастливая очередь!

Дальнейшее чтение

Если вы хотите быть уведомленным о новых статьях, следуйте nystudio107. в Твиттере.

Copyright © 2020 Nystudio107. Разработанный Nystudio107.

Оригинал: «https://dev.to/gaijinity/robust-queue-job-handling-in-craft-cms-1m0g»