Вопрос проверяет понимание того, как правильно завершать фоновые процессы и воркеры.
Graceful shutdown — это завершение воркера без резкого прерывания текущей задачи. Для этого воркер должен уметь ловить сигналы (SIGTERM, SIGINT), прекращать принимать новые сообщения и корректно завершать обработку текущего. После завершения работы нужно подтвердить или вернуть сообщение в очередь. В PHP это реализуется через pcntl-сигналы, флаги остановки и аккуратное управление циклом обработки.
Graceful shutdown необходим, чтобы гарантировать отсутствие потерь сообщений и корректное завершение фоновых задач.
Если воркер убить:
текущая задача оборвётся
сообщение останется "висеть"
бизнес-логика может быть частично выполнена
данные могут оказаться в неконсистентном состоянии
Требуется аккуратное завершение.
В PHP используют расширение pcntl:
php
pcntl_async_signals(true);
$shouldStop = false;
pcntl_signal(SIGTERM, function() use (&$shouldStop) {
$shouldStop = true;
});
Цикл обработки должен проверять флаг:
php
while (!$shouldStop) {
$msg = $queue->get(); // блокирующий вызов по возможности обернуть
process($msg);
}
После получения сигнала:
не брать новые сообщения
завершить текущую обработку
подтвердить или откатить сообщение
Важно: не завершать воркер мгновенно.
Есть 2 варианта:
успешная обработка → ack
ошибка → nack/requeue
Это гарантирует отсутствие потерь.
Если воркер блокируется на чтении:
нужно использовать таймауты
или неблокирующие вызовы
или поток с heartbeat
Graceful shutdown не должен длиться бесконечно.
Обычно:
30–60 секунд
затем воркер завершает выполнение принудительно
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";
логировать факт получения сигнала
отдавать SIGKILL только после timeout
использовать supervisor, systemd или Kubernetes lifecycle hooks
для контейнеров — корректная работа с PID1
Graceful shutdown — обязательный элемент для надёжных воркеров. Он включает ловлю сигналов, остановку принятия новых задач, завершение текущих задач и корректное подтверждение сообщений. Это предотвращает потерю данных и обеспечивает прогнозируемое поведение сервисов.