- Введение
- Установка
- Обновление Horizon
- Запуск Horizon
- Теги
- Уведомления
- Метрики
- Удаление неудачных заданий
- Очистка заданий из очередей
#Введение
Прежде чем углубляться в Laravel Horizon, рекомендуется ознакомиться с базовыми сервисами очередей Laravel. Horizon расширяет возможности очередей Laravel дополнительными функциями, которые могут показаться сложными, если вы не знакомы с базовыми возможностями очередей в Laravel.
Laravel Horizon предоставляет удобную панель управления и конфигурацию через код для ваших Redis очередей на базе Laravel. Horizon позволяет легко отслеживать ключевые метрики вашей системы очередей, такие как пропускная способность заданий, время выполнения и количество неудачных заданий.
При использовании Horizon вся конфигурация воркеров очереди хранится в одном простом конфигурационном файле. Определяя конфигурацию воркеров вашего приложения в файле под управлением версий, вы можете легко масштабировать или изменять воркеры очереди при развертывании приложения.
#Установка
Laravel Horizon требует использования Redis для работы очередей. Поэтому убедитесь, что в конфигурационном файле вашего приложения config/queue.php соединение очереди установлено в redis.
Вы можете установить Horizon в ваш проект с помощью менеджера пакетов Composer:
composer require laravel/horizon
После установки Horizon опубликуйте его ресурсы с помощью Artisan-команды horizon:install:
php artisan horizon:install
#Настройка
После публикации ресурсов Horizon основной конфигурационный файл будет находиться по пути config/horizon.php. Этот файл позволяет настроить параметры воркеров очереди для вашего приложения. Каждая опция конфигурации содержит описание её назначения, поэтому рекомендуется внимательно изучить этот файл.
Horizon использует внутренне Redis-соединение с именем horizon. Это имя зарезервировано и не должно использоваться для других Redis-соединений в файле конфигурации database.php или в опции use в файле horizon.php.
#Окружения
После установки основная опция конфигурации Horizon, с которой следует ознакомиться, — это environments. Эта опция представляет собой массив окружений, на которых работает ваше приложение, и определяет параметры процессов воркеров для каждого окружения. По умолчанию в этом массиве есть окружения production и local. Вы можете добавлять другие окружения по мере необходимости:
'environments' => [
'production' => [
'supervisor-1' => [
'maxProcesses' => 10,
'balanceMaxShift' => 1,
'balanceCooldown' => 3,
],
],
'local' => [
'supervisor-1' => [
'maxProcesses' => 3,
],
],
],
При запуске Horizon он будет использовать параметры конфигурации процессов воркеров для окружения, в котором работает ваше приложение. Обычно окружение определяется значением переменной окружения APP_ENV (environment variable). Например, стандартное окружение local настроено на запуск трёх процессов воркеров с автоматической балансировкой количества процессов между очередями. Окружение production по умолчанию запускает максимум 10 процессов воркеров с автоматической балансировкой.
Убедитесь, что в разделе environments вашего конфигурационного файла horizon есть запись для каждого окружения, на котором вы планируете запускать Horizon.
#Супервайзеры
Как видно из стандартного конфигурационного файла Horizon, каждое окружение может содержать одного или нескольких «супервайзеров». По умолчанию в конфигурации определён супервайзер с именем supervisor-1, но вы можете назвать супервайзеров как угодно. Каждый супервайзер отвечает за «наблюдение» за группой процессов воркеров и управляет балансировкой процессов между очередями.
Вы можете добавить дополнительных супервайзеров в конкретное окружение, если хотите определить новую группу процессов воркеров для этого окружения. Это полезно, если вы хотите задать другую стратегию балансировки или количество процессов воркеров для определённой очереди вашего приложения.
#Режим обслуживания
Когда ваше приложение находится в режиме обслуживания, задания из очереди не будут обрабатываться Horizon, если только в конфигурационном файле Horizon для супервайзера не задан параметр force со значением true:
'environments' => [
'production' => [
'supervisor-1' => [
// ...
'force' => true,
],
],
],
#Значения по умолчанию
В стандартном конфигурационном файле Horizon есть опция defaults. Она задаёт значения по умолчанию для ваших супервайзеров. Значения по умолчанию будут объединены с конфигурацией каждого супервайзера в окружениях, что позволяет избежать избыточного повторения при определении супервайзеров.
#Стратегии балансировки
В отличие от стандартной системы очередей Laravel, Horizon позволяет выбирать из трёх стратегий балансировки воркеров: simple, auto и false. Стратегия simple равномерно распределяет входящие задания между процессами воркеров:
'balance' => 'simple',
Стратегия auto, которая используется по умолчанию в конфигурационном файле, регулирует количество процессов воркеров на очередь в зависимости от текущей нагрузки. Например, если в очереди notifications 1000 ожидающих заданий, а очередь render пуста, Horizon выделит больше воркеров для очереди notifications до её опустошения.
При использовании стратегии auto вы можете задать опции minProcesses и maxProcesses для контроля минимального и максимального количества процессов воркеров, к которым Horizon может масштабироваться:
'environments' => [
'production' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default'],
'balance' => 'auto',
'autoScalingStrategy' => 'time',
'minProcesses' => 1,
'maxProcesses' => 10,
'balanceMaxShift' => 1,
'balanceCooldown' => 3,
'tries' => 3,
],
],
],
Опция autoScalingStrategy определяет, будет ли Horizon выделять больше процессов воркеров на основе общего времени, необходимого для обработки очереди (time), или на основе общего количества заданий в очереди (size).
Опции balanceMaxShift и balanceCooldown регулируют скорость масштабирования Horizon для удовлетворения потребностей воркеров. В приведённом примере максимум один новый процесс создаётся или уничтожается каждые три секунды. Вы можете настроить эти значения в зависимости от потребностей вашего приложения.
Если опция balance установлена в false, будет использоваться стандартное поведение Laravel, при котором очереди обрабатываются в порядке их перечисления в конфигурации.
#Авторизация панели управления
Панель управления Horizon доступна по маршруту /horizon. По умолчанию доступ к панели возможен только в окружении local. Однако в файле app/Providers/HorizonServiceProvider.php определён authorization gate, который контролирует доступ к Horizon в не локальных окружениях. Вы можете изменить этот gate по своему усмотрению для ограничения доступа к Horizon:
/**
* Зарегистрировать gate для Horizon.
*
* Этот gate определяет, кто может получить доступ к Horizon в не локальных окружениях.
*/
protected function gate(): void
{
Gate::define('viewHorizon', function (User $user) {
return in_array($user->email, [
'taylor@laravel.com',
]);
});
}
#Альтернативные стратегии аутентификации
Помните, что Laravel автоматически передаёт аутентифицированного пользователя в замыкание gate. Если безопасность Horizon обеспечивается другим способом, например, ограничением по IP, пользователям Horizon может не требоваться вход в систему. В этом случае измените сигнатуру замыкания с function (User $user) на function (User $user = null), чтобы Laravel не требовал аутентификацию.
#Подавленные задания
Иногда вам может не понадобиться отображать определённые задания, отправленные вашим приложением или сторонними пакетами. Вместо того чтобы эти задания занимали место в списке «Выполненных заданий», вы можете подавить их отображение. Для этого добавьте имя класса задания в опцию silenced в конфигурационном файле horizon вашего приложения:
'silenced' => [
App\Jobs\ProcessPodcast::class,
],
Альтернативно, задание, которое вы хотите подавить, может реализовать интерфейс Laravel\Horizon\Contracts\Silenced. Если задание реализует этот интерфейс, оно будет автоматически подавлено, даже если не указано в массиве silenced:
use Laravel\Horizon\Contracts\Silenced;
class ProcessPodcast implements ShouldQueue, Silenced
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
// ...
}
#Обновление Horizon
При обновлении до новой мажорной версии Horizon важно внимательно ознакомиться с руководством по обновлению. Кроме того, при обновлении любой версии Horizon следует повторно публиковать его ресурсы:
php artisan horizon:publish
Чтобы ресурсы всегда были актуальными и избежать проблем при будущих обновлениях, вы можете добавить команду vendor:publish --tag=laravel-assets в скрипты post-update-cmd в файле composer.json вашего приложения:
{
"scripts": {
"post-update-cmd": [
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
]
}
}
#Запуск Horizon
После настройки супервайзеров и воркеров в конфигурационном файле config/horizon.php вашего приложения вы можете запустить Horizon с помощью Artisan-команды horizon. Эта команда запустит все настроенные процессы воркеров для текущего окружения:
php artisan horizon
Вы можете приостановить процесс Horizon и возобновить обработку заданий с помощью команд Artisan horizon:pause и horizon:continue:
php artisan horizon:pause
php artisan horizon:continue
Также можно приостанавливать и возобновлять работу конкретных супервайзеров Horizon с помощью команд Artisan horizon:pause-supervisor и horizon:continue-supervisor:
php artisan horizon:pause-supervisor supervisor-1
php artisan horizon:continue-supervisor supervisor-1
Текущий статус процесса Horizon можно проверить с помощью команды Artisan horizon:status:
php artisan horizon:status
Вы можете корректно завершить процесс Horizon с помощью команды Artisan horizon:terminate. Все задания, которые в данный момент обрабатываются, будут завершены, после чего Horizon остановится:
php artisan horizon:terminate
#Развёртывание Horizon
Когда вы будете готовы развернуть Horizon на реальном сервере вашего приложения, следует настроить мониторинг процесса, который будет следить за командой php artisan horizon и перезапускать её в случае неожиданного завершения. Не волнуйтесь, ниже мы расскажем, как установить мониторинг процессов.
В процессе развертывания приложения следует указать процессу Horizon завершиться, чтобы мониторинг мог перезапустить его и применить изменения кода:
php artisan horizon:terminate
#Установка Supervisor
Supervisor — это монитор процессов для операционной системы Linux, который автоматически перезапускает процесс horizon, если он прекращает работу. Для установки Supervisor на Ubuntu используйте следующую команду. Если вы используете другую ОС, скорее всего, Supervisor можно установить через менеджер пакетов вашей системы:
sudo apt-get install supervisor
Если самостоятельная настройка Supervisor кажется сложной, рассмотрите возможность использования Laravel Forge, который автоматически установит и настроит Supervisor для ваших проектов Laravel.
#Конфигурация Supervisor
Файлы конфигурации Supervisor обычно хранятся в каталоге /etc/supervisor/conf.d на вашем сервере. В этом каталоге вы можете создавать любое количество конфигурационных файлов, которые указывают Supervisor, как мониторить ваши процессы. Например, создадим файл horizon.conf, который запускает и контролирует процесс horizon:
[program:horizon]
process_name=%(program_name)s
command=php /home/forge/example.com/artisan horizon
autostart=true
autorestart=true
user=forge
redirect_stderr=true
stdout_logfile=/home/forge/example.com/horizon.log
stopwaitsecs=3600
При определении конфигурации Supervisor убедитесь, что значение stopwaitsecs больше времени выполнения вашего самого длительного задания. Иначе Supervisor может завершить задание до его окончания.
Хотя приведённые примеры подходят для серверов на базе Ubuntu, расположение и расширение файлов конфигурации Supervisor могут отличаться в других операционных системах. Обратитесь к документации вашего сервера для получения подробностей.
#Запуск Supervisor
После создания конфигурационного файла вы можете обновить конфигурацию Supervisor и запустить контролируемые процессы с помощью следующих команд:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start horizon
Для получения дополнительной информации о работе с Supervisor обратитесь к документации Supervisor.
#Теги
Horizon позволяет назначать «теги» заданиям, включая mailables, broadcast-события, уведомления и слушатели очередей. На самом деле Horizon автоматически и интеллектуально тегирует большинство заданий в зависимости от Eloquent моделей, связанных с заданием. Например, рассмотрим следующее задание:
<?php
namespace App\Jobs;
use App\Models\Video;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class RenderVideo implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Создать новый экземпляр задания.
*/
public function __construct(
public Video $video,
) {}
/**
* Выполнить задание.
*/
public function handle(): void
{
// ...
}
}
Если это задание поставлено в очередь с экземпляром App\Models\Video, у которого атрибут id равен 1, оно автоматически получит тег App\Models\Video:1. Это происходит потому, что Horizon ищет в свойствах задания Eloquent модели. Если модели найдены, Horizon интеллектуально тегирует задание, используя имя класса модели и её первичный ключ:
use App\Jobs\RenderVideo;
use App\Models\Video;
$video = Video::find(1);
RenderVideo::dispatch($video);
#Ручное назначение тегов заданиям
Если вы хотите вручную определить теги для одного из ваших объектов, помещаемых в очередь, вы можете определить метод tags в классе:
class RenderVideo implements ShouldQueue
{
/**
* Получить теги, которые должны быть назначены заданию.
*
* @return array<int, string>
*/
public function tags(): array
{
return ['render', 'video:'.$this->video->id];
}
}
#Ручное назначение тегов слушателям событий
При получении тегов для слушателя очереди Horizon автоматически передаёт экземпляр события в метод tags, что позволяет добавить данные события в теги:
class SendRenderNotifications implements ShouldQueue
{
/**
* Получить теги, которые должны быть назначены слушателю.
*
* @return array<int, string>
*/
public function tags(VideoRendered $event): array
{
return ['video:'.$event->video->id];
}
}
#Уведомления
При настройке Horizon для отправки уведомлений в Slack или SMS следует ознакомиться с требованиями для соответствующего канала уведомлений.
Если вы хотите получать уведомления при длительном времени ожидания в одной из ваших очередей, вы можете использовать методы Horizon::routeMailNotificationsTo, Horizon::routeSlackNotificationsTo и Horizon::routeSmsNotificationsTo. Эти методы можно вызвать из метода boot вашего App\Providers\HorizonServiceProvider:
/**
* Инициализация сервисов приложения.
*/
public function boot(): void
{
parent::boot();
Horizon::routeSmsNotificationsTo('15556667777');
Horizon::routeMailNotificationsTo('example@example.com');
Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
}
#Настройка порогов времени ожидания уведомлений
Вы можете настроить, сколько секунд считается «длительным ожиданием» в конфигурационном файле config/horizon.php вашего приложения. Опция waits позволяет контролировать порог длительного ожидания для каждой комбинации соединения и очереди. Для неуказанных комбинаций используется значение по умолчанию — 60 секунд:
'waits' => [
'redis:critical' => 30,
'redis:default' => 60,
'redis:batch' => 120,
],
#Метрики
Horizon включает панель метрик, которая предоставляет информацию о времени ожидания заданий и пропускной способности очередей. Чтобы заполнять эту панель, настройте выполнение Artisan-команды snapshot Horizon каждые пять минут через планировщик вашего приложения:
/**
* Определить расписание команд приложения.
*/
protected function schedule(Schedule $schedule): void
{
$schedule->command('horizon:snapshot')->everyFiveMinutes();
}
#Удаление неудачных заданий
Если вы хотите удалить неудачное задание, используйте команду horizon:forget. Команда horizon:forget принимает в качестве единственного аргумента ID или UUID неудачного задания:
php artisan horizon:forget 5
#Очистка заданий из очередей
Если вы хотите удалить все задания из очереди по умолчанию вашего приложения, используйте Artisan-команду horizon:clear:
php artisan horizon:clear
Вы можете указать опцию queue для удаления заданий из конкретной очереди:
php artisan horizon:clear --queue=emails