Установка Cavalcade на сервер / VPS

29 апреля 2020 138 WordPress

Что такое Cavalcade

Cavalcade — это система управления задачами WordPress, созданная компанией HumanMade, для замены встроенного в движок псевдо-крона, который имеет некоторые недостатки:

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

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

Принцип работы кавалькады

Кавалькада также разработана с учетом поддержки горизонтального масштабирования. Для сайтов с большим трафиком и несколькими серверами приложений Вы можете установить раннер на каждом сервере приложений, что ускорит обработку заданий. Также можно поднять отдельные сервера для раннеров. А в сочетании с группами автоматического масштабирования AWS EC2 можно плавно менять мощность группы серверов обработки заданий.

Кавалькада состоит из двух частей:

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

Установка плагина

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

Переходим в mu-plugins сайта:

cd /path/to/site/wp-content/mu-plugins

Если директории mu-plugins еще нет, то создаем ее:

mkdir /path/to/site/wp-content/mu-plugins

Затем клонируем плагин из репозитория разработчиков в эту директорию:

git clone https://github.com/humanmade/Cavalcade

Создаем плагин-заглушку в виде php файла, где подключаем ранее загруженный плагин (название файла и описание плагина произвольное):

<?php
/**
Plugin Name: Cavalcade
Description: Cavalcade is a scalable job system, designed as a drop-in replacement for WordPress's built-in pseudo-cron system.
Version: 2.0
Author: Human Made
Author URI: https://github.com/humanmade/
License: GPLv2
 */

require_once __DIR__ . '/Cavalcade/plugin.php';

Добавленный плагин должен появится в списке необходимых плагинов:

И отключаем встроенный в WordPress крон в wp-config.php:

define( 'DISABLE_WP_CRON', true );

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

Сначала нужно клонировать с репозитория разработчиков сам раннер на наш сервер в любую директорию (в моем случае качаю в /opt):

cd /opt
git clone https://github.com/humanmade/Cavalcade-Runner

Затем создаем ссылку на бинарник раннера в любую из директорий с бинарниками (в моем случае в /usr/bin, далее будем указывать путь к бинарнику из этой директории):

ln -s /opt/Cavalcade-Runner/bin/cavalcade /usr/bin/

Теперь нам нужно сделать раннер системным сервисом (демоном) для его постоянной работы. Для этого можно воспользоваться любым средством демонизации (systemd, upstart, init, nohup).

Я использую демонизацию через systemd. Имя конфига обычно делаю из 2х частей через точку: cavalcade (для указания, что это сервис кавалькады) и имя проекта (для уникализации сервиса, если планируется посадить на кавалькаду несколько сайтов на сервере).

Создаем конфиг сервиса (/lib/systemd/system/cavalcade.myproject.service) со следующим содержимым:

[Unit]
Description=CavalcadeRunner (MyProject)

[Service]
TimeoutStartSec=0
TimeoutStopSec=600
RestartSec=5
Restart=always
WorkingDirectory=/path/to/project/root
User=project_user
ExecStart=/usr/bin/cavalcade

[Install]
WantedBy=multi-user.target

где нужно отредактировать следующее:

  • Description — произвольное описание сервиса;
  • RestartSec — периодичность в секундах перезапуска сервиса при сбоях или недоступности базы данных;
  • WorkingDirectory — абсолютный путь к корню сайта;
  • User — системный пользователь, под которым работает сайт;
  • ExecStart — путь к бинарнику / ссылке на бинарник раннера.

Остальное не трогаем и оставляем как есть.

Обратите внимание на то, что сервис будет падать при недоступности базы данных или ее перезагрузке. Параметр RestartSec задает периодичность перезагрузок сервиса после его падения. Если сервис не сможет нормально запуститься через определенное количество перезапусков, то его нужно будет перезапускать вручную. Если сервис не будет успевать стартовать при перезапуске базы данных, то нужно откорректировать значение RestartSec. Также можете посмотреть параметры StartLimitIntervalSec и StartLimitBurst.

Также для нормальной работы раннера необходимо php расширение pcntl для управления процессами из php. Убедитесь, что это расширение стоит и функции pcntl_* не отключены в конфиге php для cli (директива disable_functions).

Теперь можно запустить сервис:

systemctl start cavalcade.myproject.service

Проверяем работу сервиса:

systemctl status cavalcade.myproject.service

Если все ок, то увидим Active: active (running):

Корректно работающий раннер Cavalcade

Если будет ошибка, то проверяем лог сервиса:

journalctl -u cavalcade.myproject.service

находим и исправляем ошибки.

После того, как сервис будет нормально работать, можно добавить его в автозапуск:

systemctl enable cavalcade.myproject.service

Проверка работы

Для проверки работы кавалькады можно создать простое задание с выводом произвольного текста:

add_filter( 'cron_schedules', 'cron_add_one_minute' );
function cron_add_one_minute( $schedules ) {
	$schedules['one_minute'] = [
		'interval' => 60,
		'display' => 'Once a minute'
	];
	return $schedules;
}

if ( ! wp_next_scheduled( 'cavalcade_check_job' ) ) {  
	wp_schedule_event( time(), 'one_minute', 'cavalcade_check_job' );  
}
add_action( 'cavalcade_check_job', 'cavalcade_check_job_callback' );  
function cavalcade_check_job_callback() {
	echo 'Cavalcade working!';
}

Результат выполнения задания можно увидеть в логе systemd (добавьте параметр -f для отображения лога в реальном времени):

journalctl -u cavalcade.myproject.service

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

Результат выполнения задачи в журнале Systemd

При наличии ошибок при выполнении задачи, они будут отображены там же в журнале.

Команды кавалькады в WP-CLI

Плагин кавалькады добавляет свои команды в wp-cli. Полный список команд можно посмотреть так:

wp help cavalcade

Рассмотрим основные команды.

Просмотр заданий

Для просмотра заданий введите:

wp cavalcade jobs

Будет выведен список всех задач с указанием информации о задачах:

Для просмотра дополнительных параметров для фильтрации и сортировки введите:

wp help cavalcade jobs

Запуск заданий

Имея id задания, мы можем его выполнить не дожидаясь планового времени выполнения:

wp cavalcade run <id>

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

Просмотр лога

Для просмотра лога выполняем:

wp cavalcade log

Лог будет выведен в виде таблицы с информацией о выполненных заданиях:

Для просмотра дополнительных параметров для фильтрации введите:

wp help cavalcade log

Скрипт для мониторинга и перезапуска раннера

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

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

#!/bin/bash

CAVALCADE_UNITS=$(find /lib/systemd/system/ -name 'cavalcade.*')

if ! [ -z "$CAVALCADE_UNITS" ]; then
	echo "$CAVALCADE_UNITS" | while read CAVALCADE_UNIT ; do
		systemctl is-active $(basename "$CAVALCADE_UNIT") >/dev/null 2>&1 ||
		systemctl restart $(basename "$CAVALCADE_UNIT")
	done
fi

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

Важно: имя сервиса должно начинаться на cavalcade., скрипт работает только с systemd.

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

* * * * * /bin/bash /полный/путь/к/скрипту

Полезные ссылки

Комментарии (0)