---
title: "Налаштування Laravel Horizon: що перевірити, коли черги перевантажують сервер"
url: https://laravelukraine.com/blog/nalastuvannia-laravel-horizon-shho-pereviriti-koli-cergi-perevantazuiut-server
date: 2026-11-13
source: https://standaniels.nl/articles/tuning-laravel-horizon
---

# Налаштування Laravel Horizon: що перевірити, коли черги перевантажують сервер

Ми самі хостимо [Mailcoach](https://www.mailcoach.app/) і керуємо його воркерами черг через Laravel Horizon. *(Mailcoach - застосунок від Spatie для email-розсилок і автоматизацій на Laravel, - прим. пер.)* Щоразу, коли Mailcoach надсилав кампанію, моніторинг повідомляв про високе навантаження на сервер, а сайт сповільнювався. Я також бачив багато активності PHP-FPM, але саме по собі це не пояснювало стрибка. Я почав із того, що звірив конфігурацію воркерів із завданнями, які ми насправді запускаємо.

### 1. З'ясуйте, хто споживає чергу

- Складіть список супервізорів Horizon і всіх окремих процесів `queue:work`.
- Порівняйте базу даних Redis, префікс ключів і назви черг, якими користується кожен воркер.

Різні назви підключень у Laravel все одно можуть вказувати на ті самі ключі черги в Redis. Якщо в цих підключень різні вікна повторної спроби, один воркер може підхопити завдання, яке інший ще виконує. Завдання, що триває десять хвилин, може запуститися двічі, якщо інший воркер використовує `retry_after` у 90 секунд.

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

### 2. Залиште запас між timeout завдання і `retry_after`

- Перевіряйте timeout на рівні завдань, а також налаштування супервізорів і окремих воркерів.
- Тримайте timeout супервізора Horizon вищим за timeout завдань і нижчим за `retry_after` підключення.
- Використовуйте однаковий `retry_after` для підключень, що ділять Redis-черги.

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

```php
// config/queue.php, у кожному Redis-підключенні, яке ділить ці черги
'retry_after' => 60 * 60,

// config/horizon.php, у налаштуваннях відповідного супервізора
'timeout' => 60 * 30,
```

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

```php
$connection = $supervisor['connection'];
$retryAfter = config("queue.connections.{$connection}.retry_after");

$this->assertLessThan($retryAfter, $supervisor['timeout']);
```

### 3. Перевірте розгортання і алерти очікування

- Переконайтеся, що під час розгортання Horizon завершується, а менеджер процесів запускає його знову вже на новому релізі.
- Зіставте кожен алерт очікування Horizon з реальною парою `connection:queue` і перевірте, що він до вас доходить.

Додайте `php artisan horizon:terminate` у своє розгортання і налаштуйте менеджер процесів, який підніматиме Horizon знову. Окремі воркери перевірте окремо.

Для розгортання застосунку я використовую [Deployer](https://deployer.org). З його рецептом для Laravel я додав у `deploy.php` таке завдання і хук:

```php
task('artisan:horizon:terminate', artisan('horizon:terminate'));
before('deploy:success', 'artisan:horizon:terminate');
```

Ключі `waits` у Horizon мають відповідати реальним парам `connection:queue`. Наприклад, цей ключ позначає чергу `send-mail` на підключенні `mailcoach-redis`:

```text
mailcoach-redis:send-mail
```

Оберіть поріг, що відповідає звичайній поведінці черги, і протестуйте маршрут сповіщень. Враховуйте навмисне обмеження швидкості (throttling): воно впливає на те, скільки завдання чекають. Час очікування в черзі і прогрес кампанії також розповідають різне, тож відстежуйте обидва, якщо вам треба знати, чи робота рухається. Подробиці конфігурації - в [документації Laravel Horizon](https://laravel.com/docs/12.x/horizon).

### 4. Вимірюйте, перш ніж змінювати кількість воркерів

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

Для Mailcoach корисно записувати:

- навантаження на сервер, доступну пам'ять і використання swap;
- використання CPU і пам'яті воркерами черг і процесами PHP-FPM;
- розміри черг поруч із прогресом кампанії;
- фактичну швидкість надсилання порівняно з вашим обмеженням і лімітами поштового провайдера.

Дивіться на ці показники разом. Черзі, що росте, можуть знадобитися додаткові воркери, але спершу перевірте, чи має сервер для них ресурси. Якщо PHP-FPM зайнятий, а воркери простоюють, дослідіть також вебзапити.

Я додав власну Artisan-команду, яка щохвилини записує ці метрики в лог, поки кампанія надсилається, і ще одну команду, що підсумовує цей лог.

### 5. Шукайте причину додати воркери

- Перевірте, чи справді робота накопичується саме в тій черзі, яку ви налаштовуєте.
- Порівняйте фактичну швидкість надсилання з вашим обмеженням і лімітом провайдера.
- Порівняйте активність воркерів і PHP-FPM у моменти стрибків навантаження.

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

Я виміряв близько 0,55 листа на секунду при обмеженні в один лист на секунду. Якщо побачу цей розрив знову, то перевірю ліміт надсилання SES, перш ніж чіпати обмеження.

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

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

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

### Читайте також

- [Воркери черг Laravel тримають у пам'яті 8 копій застосунку](https://laravelukraine.com/blog/vorkeri-cerg-laravel-trimaiut-u-pamiati-8-kopii-zastosunku)
- [Go вимірює, Laravel вирішує: як Sentinel замінив регіональні воркери Horizon на Go-проби](https://laravelukraine.com/blog/go-vimiriuje-laravel-virisuje-iak-sentinel-zaminiv-regionalni-vorkeri-horizon-na-go-probi)
