1. Пакеты
  2. Laravel Horizon

Присоединяйся к нашему Telegram сообществу @webblend!

Здесь ты найдешь сниппеты по Laravel и полезные советы по веб-разработке.

Введение

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

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

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

Установка

Внимание Для работы Laravel Horizon необходимо использовать Redis для управления вашей очередью. Поэтому убедитесь, что ваше соединение с очередью установлено в redis в файле конфигурации вашего приложения config/queue.php.

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

composer require laravel/horizon

После установки Horizon опубликуйте его ресурсы с помощью команды Artisan horizon:install:

php artisan horizon:install

Настройка

После публикации ресурсов Horizon его основной файл конфигурации будет расположен в config/horizon.php. Этот файл конфигурации позволяет настраивать параметры рабочего процесса очереди для вашего приложения. Каждая опция конфигурации содержит описание своего назначения, поэтому обязательно внимательно изучите этот файл.

Внимание Horizon использует внутреннее соединение Redis с именем horizon. Это имя соединения Redis зарезервировано и не должно быть присвоено другому соединению 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 переменной среды. Например, для окружения local по умолчанию конфигурация Horizon настроена на запуск трех рабочих процессов и автоматическое балансирование числа рабочих процессов, назначенных каждой очереди. Для окружения production по умолчанию настроено максимум 10 рабочих процессов и автоматическое балансирование числа рабочих процессов, назначенных каждой очереди.

Внимание Убедитесь, что раздел environments файла конфигурации horizon содержит запись для каждого окружения, на котором вы планируете запускать Horizon.

Надзиратели

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

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

Значения по умолчанию

В файле конфигурации 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 вашего приложения есть определение ворот доступа. Эта ворота доступа управляет доступом к Horizon в не локальных средах. Вы вольны изменять эту ворота по мере необходимости для ограничения доступа к вашей установке Horizon:

/**
* Зарегистрируйте ворота Horizon.
*
* Эти ворота определяют, кто может получить доступ к Horizon в средах, отличных от локальных.
*/
protected function gate(): void
{
Gate::define('viewHorizon', function (User $user) {
return in_array($user->email, [
]);
});
}

Альтернативные стратегии аутентификации

Помните, что Laravel автоматически внедряет аутентифицированного пользователя в замыкание ворот. Если ваше приложение предоставляет безопасность 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 вы должны повторно опубликовать ресурсы 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, вы можете использовать следующую команду. Если вы не используете Ubuntu, вы, вероятно, можете установить Supervisor с использованием менеджера пакетов вашей операционной системы:

sudo apt-get install supervisor

Примечание Если настройка Supervisor кажется вам сложной задачей, рассмотрите возможность использования Laravel Forge, который автоматически установит и настроит Supervisor для ваших проектов Laravel.

Настройка Supervisor

Файлы конфигурации Supervisor обычно хранятся в каталоге /etc/supervisor/conf.d вашего сервера. В этом каталоге вы можете создать любое количество файлов конфигурации, которые указывают, как ваши процессы должны быть отслеживаемыми. Например, давайте создадим файл 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 позволяет назначать «теги» задачам, включая почтовые сообщения, широковещательные события, уведомления и задачи прослушивателей событий в очереди. Фактически 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. Если модели 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 для отправки уведомлений в Slack или SMS рекомендуется ознакомиться с предварительными требованиями для соответствующего канала уведомлений.

Если вы хотите получать уведомления, когда одна из ваших очередей имеет длительное время ожидания, вы можете использовать методы Horizon::routeMailNotificationsTo, Horizon::routeSlackNotificationsTo и Horizon::routeSmsNotificationsTo. Вы можете вызвать эти методы из метода boot ваших App\Providers\HorizonServiceProvider:

/**
* Загрузите любые службы приложения.
*/
public function boot(): void
{
parent::boot();
 
Horizon::routeSmsNotificationsTo('15556667777');
Horizon::routeMailNotificationsTo('[email protected]');
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 принимает идентификатор или UUID неудачной задачи в качестве единственного аргумента:

php artisan horizon:forget 5

Очистка задач из очередей

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

php artisan horizon:clear

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

php artisan horizon:clear --queue=emails