Любите загадки? Событие еще доступно на сайте.
Поддержите нас - каждый вклад важен!
Поддержите нас - каждый вклад важен!

Laravel Horizon

Вы просматриваете документ для прошлой версии.
Рассмотрите возможность обновления вашего проекта до актуальной версии 10.x. Почему это важно?

Вступление

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

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

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

horizon-example.png

Установка

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 переменной среды. Например, стандартная локальная среда Horizon настроена на запуск трех рабочих процессов и автоматическое выравнивание количества рабочих процессов, назначенных каждой очереди. По умолчанию рабочая среда настроена на запуск максимум 10 рабочих процессов и автоматический баланс количества рабочих процессов, назначенных каждой очереди.

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

Supervisors (Наблюдатели)

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

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

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

В файле конфигурации Horizon по умолчанию вы заметите параметр конфигурации defaults. Эта опция конфигурации определяет значения по умолчанию для Supervisors приложения. Значения конфигурации супервизора по умолчанию будут объединены с конфигурацией супервизора для каждой среды, что позволит вам избежать ненужного повторения при определении супервизоров.

Стратегии балансировки

В отличие от стандартной системы очередей Laravel, Horizon позволяет вам выбирать из трех стратегий балансировки рабочих процессов (worker): 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',
            'minProcesses' => 1,
            'maxProcesses' => 10,
            'balanceMaxShift' => 1,
            'balanceCooldown' => 3,
            'tries' => 3,
        ],
    ],
],

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

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

Авторизация в информационной панели (dashboard)

Horizon предоставляет информационную панель (dashboard) по URI /horizon. По умолчанию вы сможете получить доступ к этой панели инструментов только в локальной среде. Однако в файле app/Providers/HorizonServiceProvider.php есть определение шлюза авторизации. Этот шлюз контролирует доступ к Horizon во внешних средах. Вы можете настроить этот шлюз по мере необходимости, чтобы ограничить доступ к вашему приложению Horizon:

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

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

Помните, что Laravel автоматически добавляет к шлюзу аутентифицированного пользователя замыкание (closure). Если ваше приложение обеспечивает безопасность Horizon с помощью другого метода, например ограничения IP-адресов, то пользователям Horizon может и не требоваться “аутентификация”. Следовательно, нужно будет изменить написание функции (сигнатуру) выше с function ($user) на function ($user = null), чтобы Laravel не требовал аутентификации.

Обновление Horizon

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

php artisan horizon:publish

Чтобы поддерживать ресурсы в актуальном состоянии и избежать проблем в будущих обновлениях, вы можете добавить команду horizon: publish к сценариям post-update-cmd в файле composer.json вашего приложения:

{
    "scripts": {
        "post-update-cmd": [
            "@php artisan horizon:publish --ansi"
        ]
    }
}

Запуск Horizon

После того как вы настроили свои супервизоры (supervisors) и рабочие процессы (workers) в файле конфигурации приложения 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 (deploy)

Когда вы будете готовы развернуть 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

Файлы конфигурации супервизора обычно хранятся в каталоге вашего сервера /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

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

Запуск Supervisor

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

sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start horizon

Для получения дополнительной информации о запуске Supervisor обратитесь к документации Supervisor.

Теги

Horizon позволяет назначать “теги” (tags) заданиям, включая почтовые сообщения, широковещательные события, уведомления и прослушиватели событий в очереди. Фактически, Horizon будет интеллектуально и автоматически помечать большинство заданий в зависимости от моделей Eloquent, прикрепленных к заданию. Например, взгляните на следующее задание (job):

<?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;

    /**
     * The video instance.
     *
     * @var \App\Models\Video
     */
    public $video;

    /**
     * Create a new job instance.
     *
     * @param  \App\Models\Video  $video
     * @return void
     */
    public function __construct(Video $video)
    {
        $this->video = $video;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //
    }
}

Если это задание поставлено в очередь с экземпляром 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
     */
    public function tags()
    {
        return ['render', 'video:'.$this->video->id];
    }
}

Уведомления

При настройке Horizon для отправки уведомлений Slack или SMS необходимо ознакомиться с предварительными условиями для соответствующего канала уведомлений.

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

/**
 * Загрузчик сервисов приложения.
 *
 * @return void
 */
public function boot()
{
    parent::boot();

    Horizon::routeSmsNotificationsTo('15556667777');
    Horizon::routeMailNotificationsTo('[email protected]');
    Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
}

Настройка пороговых значений времени ожидания уведомлений

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

'waits' => [
    'redis:default' => 60,
    'redis:critical,high' => 90,
],

Метрики

Horizon включает панель показателей, которая предоставляет информацию о времени ожидания и пропускной способности вашего задания и очереди. Чтобы заполнить эту информационную панель, вы должны настроить Artisan-команду Horizon snapshot на запуск каждые пять минут через планировщик (scheduler) вашего приложения:

/**
 * Определение расписания для команд.
 *
 * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
 * @return void
 */
protected function schedule(Schedule $schedule)
{
    $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