Graceful shutdown и жизненный цикл приложения
↑ 3.5 Инфраструктура приложения: ошибки, health checks, фоновые задачи · ← Предыдущая · → Следующая
Зачем это на собесе
Как не терять запросы при деплое в Kubernetes.
Объяснение
Последовательность при остановке: сигнал SIGTERM → IHostApplicationLifetime.ApplicationStopping → сервер перестаёт принимать новые соединения и ждёт текущие → остановка IHostedService (в обратном порядке) → ApplicationStopped.
builder.Services.Configure<HostOptions>(o => o.ShutdownTimeout = TimeSpan.FromSeconds(30));
lifetime.ApplicationStopping.Register(() => log.LogInformation("Stopping..."));В Kubernetes:
- Под получает
Terminating, его убирают из endpoints (readiness). - Параллельно отправляется SIGTERM.
- По истечении
terminationGracePeriodSeconds— SIGKILL.
Из-за гонки между удалением из балансировки и SIGTERM короткая задержка в preStop (sleep 5) предотвращает потерю запросов.
Что делать при остановке
- Завершить in-flight запросы, не принимать новые.
- Остановить консюмеры: перестать читать, закончить текущее, закоммитить offset.
- Сбросить буферы (логи, метрики, outbox).
- Освободить блокировки и соединения.
Нюансы и подводные камни
ShutdownTimeoutпо умолчанию 30 секунд (в .NET 6+); должен быть меньшеterminationGracePeriodSeconds.- PID 1 в контейнере: используйте
execв entrypoint, чтобы сигнал дошёл до процесса. - Долгие запросы должны реагировать на
RequestAborted/ApplicationStopping. - Данные в памяти, не сохранённые до остановки, теряются: используйте очереди и транзакции.
Практика
- Отправьте SIGTERM во время запроса и убедитесь, что он завершился.
- Добавьте
preStopи проверьте отсутствие 502 при rolling update. - Корректно остановите Kafka consumer.
Вопросы с ответами
Что происходит при SIGTERM в ASP.NET Core?
Хост начинает остановку: прекращает приём новых запросов, ждёт текущих до
ShutdownTimeout, останавливает hosted services.
Почему при деплое бывают 502?
Под ещё в балансировке, но уже остановился; лечится readiness,
preStopи graceful shutdown.