Как сделать graceful shutdown
Вопрос
Как бы ты реализовал корректное завершение Node-сервиса при деплое?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Ловим SIGTERM (и SIGINT для локального запуска)
server.close(): новые соединения не принимаем, текущие дорабатываем
Readiness-проба переходит в «не готов», чтобы балансировщик снял трафик
Закрываем пулы БД, Redis, консьюмеры очередей
Таймаут: если не успели, выходим принудительно до SIGKILL
keep-alive соединения: closeIdleConnections или заголовок Connection: close
Что могут спросить следом
- Что произойдёт, если не обрабатывать SIGTERM в Docker?
- Как быть с долгими задачами из очереди?
- Почему процесс в контейнере может не получить сигнал, если запущен через npm start?
Разбор
Оркестратор при деплое шлёт SIGTERM и ждёт, а через таймаут, в Docker это 10 секунд, добивает SIGKILL. Моя задача уложиться в это время, не порвав запросы.
В обработчике SIGTERM я сначала помечаю сервис как неготовый, чтобы балансировщик перестал слать трафик. Затем вызываю server.close: новые соединения не принимаются, текущие запросы дорабатывают. Простаивающие keep-alive соединения закрываю через closeIdleConnections, иначе close будет ждать их долго.
Потом закрываю пулы к базе и Redis, останавливаю консьюмеры очередей, чтобы они не брали новые задачи, а взятые доделали или вернули. И ставлю страховочный таймер: если за несколько секунд не успели, выходим с ненулевым кодом сами.
Важная деталь: в контейнере процесс должен быть PID 1 или запускаться через init вроде tini, а не через npm start, иначе сигнал может не дойти до Node.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.