Черга відокремлює прийняття запиту від виконання роботи. Веб-запит лише ставить задачу в чергу й одразу відповідає, а воркери виконують її у фоні.
Що варто винести в чергу:
- повільні операції: генерація PDF і звітів, обробка зображень і відео, імпорт файлів;
- виклики сторонніх сервісів: листи, SMS, push, вебхуки, синхронізація з CRM - вони можуть бути повільними чи недоступними;
- масові дії: розсилка тисячам користувачів, перерахунок статистики;
- те, що не потрібне для відповіді користувачу прямо зараз.
Що черги дають архітектурі:
- швидкі відповіді: користувач не чекає на відправку листа чи відповідь API банку;
- стійкість до збоїв: якщо сторонній сервіс недоступний, задача повториться (
$tries,backoff), а запит користувача не впаде; - згладжування навантаження: пік запитів створює чергу задач, яку воркери обробляють у своєму темпі, а не перевантажує базу й сторонні API;
- незалежне масштабування: воркерів можна додавати окремо від вебсерверів; різні черги (
emails,reports,default) - з різною кількістю воркерів і пріоритетами; - обмеження частоти до сторонніх API (
RateLimited,ThrottlesExceptionsmiddleware для джоб).
Що треба враховувати при проєктуванні:
- ідемпотентність: задача може виконатися більше одного разу (повтор після тайм-ауту, перезапуск воркера) - повторне виконання не має дублювати списання чи листи;
- eventual consistency: результат з'являється не одразу - інтерфейс має показувати стан «в обробці»;
- транзакції: задача, поставлена всередині транзакції, може запуститися до коміту й не знайти дані -
afterCommit(); - дані в задачі: моделі серіалізуються як ідентифікатори (
SerializesModels) і перезавантажуються - стан на момент виконання може відрізнятися від стану на момент постановки; - моніторинг: невдалі задачі (
failed_jobs), довжина черги, час очікування - Horizon для Redis-черг; - деплой: воркери тримають старий код у пам'яті - після деплою
php artisan queue:restart.
Драйвери: database (просто, без додаткової інфраструктури), Redis (швидко, з Horizon), SQS та інші керовані сервіси.