Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Задачи

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про PHP: graceful, shutdown

Как организовать корректный graceful shutdown воркеров в PHP, чтобы завершить начатые задачи без потерь?

Вопрос проверяет понимание того, как правильно завершать фоновые процессы и воркеры.

Короткий ответ

Graceful shutdown — это завершение воркера без резкого прерывания текущей задачи. Для этого воркер должен уметь ловить сигналы (SIGTERM, SIGINT), прекращать принимать новые сообщения и корректно завершать обработку текущего. После завершения работы нужно подтвердить или вернуть сообщение в очередь. В PHP это реализуется через pcntl-сигналы, флаги остановки и аккуратное управление циклом обработки.

Длинный ответ

Как реализовать корректный graceful shutdown воркеров

Graceful shutdown необходим, чтобы гарантировать отсутствие потерь сообщений и корректное завершение фоновых задач.

1. Проблема резкого завершения

Если воркер убить:

  • текущая задача оборвётся

  • сообщение останется "висеть"

  • бизнес-логика может быть частично выполнена

  • данные могут оказаться в неконсистентном состоянии

Требуется аккуратное завершение.


2. Основные шаги graceful shutdown

1. Ловля сигналов

В PHP используют расширение pcntl:

php

pcntl_async_signals(true);

$shouldStop = false;

pcntl_signal(SIGTERM, function() use (&$shouldStop) {
    $shouldStop = true;
});

2. Прекращение принятия новых сообщений

Цикл обработки должен проверять флаг:

php

while (!$shouldStop) {
    $msg = $queue->get(); // блокирующий вызов по возможности обернуть
    process($msg);
}

3. Завершение текущей задачи

После получения сигнала:

  • не брать новые сообщения

  • завершить текущую обработку

  • подтвердить или откатить сообщение

Важно: не завершать воркер мгновенно.


3. Подтверждение сообщений

Есть 2 варианта:

  1. успешная обработка → ack

  2. ошибка → nack/requeue

Это гарантирует отсутствие потерь.


4. Управление блокирующими вызовами

Если воркер блокируется на чтении:

  • нужно использовать таймауты

  • или неблокирующие вызовы

  • или поток с heartbeat


5. Тайм-аут на завершение

Graceful shutdown не должен длиться бесконечно.
Обычно:

  • 30–60 секунд

  • затем воркер завершает выполнение принудительно


6. Пример мини-реализации

php

pcntl_async_signals(true);

$stop = false;
pcntl_signal(SIGTERM, fn() => $stop = true);

while (true) {
    if ($stop) break;

    $msg = $channel->basic_get('queue');

    if ($msg) {
        try {
            handle($msg);
            $channel->basic_ack($msg->delivery_info['delivery_tag']);
        } catch (Throwable $e) {
            $channel->basic_nack($msg->delivery_info['delivery_tag'], requeue: true);
        }
    }

    usleep(50000);
}

echo "Worker stopped gracefully\n";

7. Дополнительные аспекты

  • логировать факт получения сигнала

  • отдавать SIGKILL только после timeout

  • использовать supervisor, systemd или Kubernetes lifecycle hooks

  • для контейнеров — корректная работа с PID1


8. Вывод

Graceful shutdown — обязательный элемент для надёжных воркеров. Он включает ловлю сигналов, остановку принятия новых задач, завершение текущих задач и корректное подтверждение сообщений. Это предотвращает потерю данных и обеспечивает прогнозируемое поведение сервисов.

  • Аватар

    PHP Guru

    Mikhail Savin

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.

Уровень

  • Рейтинг:

    5

  • Сложность:

    7

Навыки

  • PHP

    PHP

Ключевые слова

#graceful

#shutdown

Подпишись на PHP Developer в телеграм

  • Аватар

    PHP Guru

    Mikhail Savin

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.