Laravel Horizon

Вступ

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

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

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

Laravel Horizon

Встановлення

Laravel Horizon вимагає, щоб ви використовували Redis для роботи вашої черги. Тому вам слід переконатися, що ваше з'єднання з чергою встановлено на redis у файлі конфігурації config/queue.php вашого застосунку.

Ви можете встановити Horizon у ваш проект, використовуючи менеджер пакетів компонувальник:

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,
        ],
    ],
],

Ви також можете визначити універсальне середовище (*), яке буде використовуватися, коли не знайдено жодного іншого відповідного середовища:

'environments' => [
    // ...
 
    '*' => [
        'supervisor-1' => [
            'maxProcesses' => 3,
        ],
    ],
],

Коли ви запускаєте Horizon, він використовуватиме параметри конфігурації процесу обробника для середовища, в якому працює ваш застосунок. Зазвичай середовище визначається значенням APP_ENV змінної середовища. Наприклад, за замовчуванням середовище Horizon local налаштоване на запуск трьох процесів обробника та автоматичне балансування кількості процесів обробника, призначених кожній черзі. За замовчуванням середовище production налаштоване на запуск максимум 10 процесів обробника та автоматичне балансування кількості процесів обробника, призначених кожній черзі.

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

Керівники

Як ви можете побачити у файлі конфігурації Horizon за замовчуванням, кожне середовище може містити одного або більше "супервізорів". За замовчуванням, файл конфігурації визначає цього супервізора як supervisor-1; однак, ви можете назвати своїх супервізорів як завгодно. Кожен супервізор фактично відповідає за "нагляд" за групою обробників і піклується про балансування обробників між чергами.

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

Режим обслуговування

Поки ваш застосунок знаходиться в режимі обслуговування, поставлені в чергу завдання не будуть оброблятися Horizon, якщо тільки опція супервізора force не визначена як true у файлі конфігурації Horizon:

'environments' => [
    'production' => [
        'supervisor-1' => [
            // ...
            'force' => true,
        ],
    ],
],

Значення за замовчуванням

У файлі конфігурації Horizon за замовчуванням ви помітите опцію конфігурації defaults. Ця опція конфігурації визначає значення за замовчуванням для супервізорів вашого застосунку. Значення конфігурації супервізора за замовчуванням будуть об'єднані з конфігурацією супервізора для кожного середовища, що дозволяє уникнути зайвого повторення при визначенні ваших супервізорів.

Стратегії Балансування

На відміну від стандартної системи черг Laravel, Horizon дозволяє вибирати з трьох стратегій балансування обробників: simple, auto та false. Стратегія simple розподіляє вхідні завдання рівномірно між процесами обробників:

'balance' => 'simple',

Стратегія auto, яка є стандартною в конфігураційному файлі, налаштовує кількість обробників процесів на чергу на основі поточного навантаження черги. Наприклад, якщо ваша черга notifications має 1,000 очікуючих завдань, тоді як ваша черга 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 gate.
 *
 * Цей шлюз визначає, хто може отримати доступ до Horizon у не-локальних середовищах.
 */
protected function gate(): void
{
    Gate::define('viewHorizon', function (User $user) {
        return in_array($user->email, [
            'example@example.com',
        ]);
    });
}

Альтернативні стратегії автентифікації

Пам'ятайте, що 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 Queueable;
 
    // ...
}

Оновлення Horizon

Коли ви оновлюєтеся до нової основної версії Horizon, важливо ретельно переглянути посібник з оновлення.

Запуск 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:supervisor-status:

php artisan horizon:supervisor-status supervisor-1

Ви можете акуратно завершити процес 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 Cloud, який може керувати фоновими процесами для ваших 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, події трансляції, сповіщення та поставлені в чергу слухачі подій. Насправді, Horizon буде інтелектуально та автоматично призначати теги для більшості завдань залежно від моделей Eloquent, які прикріплені до завдання. Наприклад, розгляньте наступне завдання:

<?php
 
namespace App\Jobs;
 
use App\Models\Video;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
 
class RenderVideo implements ShouldQueue
{
    use Queueable;
 
    /**
     * Створити новий екземпляр завдання.
     */
    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 автоматично передасть екземпляр події до методу 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 команду Horizon snapshot для запуску кожні п'ять хвилин у файлі routes/console.php вашого застосунку:

use Illuminate\Support\Facades\Schedule;
 
Schedule::command('horizon:snapshot')->everyFiveMinutes();

Якщо ви хочете видалити всі дані метрик, ви можете викликати команду Artisan horizon:clear-metrics:

php artisan horizon:clear-metrics

Видалення невдалих завдань

Якщо ви хочете видалити невдалу задачу, ви можете скористатися командою horizon:forget. Команда horizon:forget приймає ID або UUID невдалої задачі як єдиний аргумент:

php artisan horizon:forget 5

Якщо ви хочете видалити всі невдалі завдання, ви можете надати опцію --all до команди horizon:forget:

php artisan horizon:forget --all

Очищення Завдань з Черг

Якщо ви хочете видалити всі завдання з черги за замовчуванням вашого застосунку, ви можете зробити це за допомогою команди Artisan horizon:clear:

php artisan horizon:clear

Ви можете надати опцію queue, щоб видалити завдання з конкретної черги:

php artisan horizon:clear --queue=emails