Как диагностировать зависание приложения
Что проверяют
Есть ли у вас порядок действий или вы сразу перезапускаете сервис. Интервьюер хочет услышать, как вы отличаете «занят работой» от «ждёт чего-то» и какие данные снимаете до рестарта. Следом часто спрашивают, как это сделать в Kubernetes, где в контейнере нет ни top, ни шелла.
Как отвечать
Первым делом зафиксируйте симптом по метрикам: растёт задержка, падает пропускная способность или процесс вовсе не отвечает на health check. Дальше главная развилка:
- процесс ест CPU:
top -H -p <PID>покажет горячий поток. Это бесконечный цикл, тяжёлое регулярное выражение или сборщик мусора, который не успевает освобождать память; - процесс спит: ждёт блокировку, сеть или диск.
strace -f -p <PID>покажет системный вызов, на котором он висит, состояниеDвpsозначает непрерываемое ожидание ввода-вывода, аiostat -x 1подтвердит проблему с диском; - исчерпан ресурс: пул соединений к базе, файловые дескрипторы (
ls /proc/<PID>/fd | wc -lпротивulimit -n), пул потоков.ss -tanpпокажет зависшие соединения; - ядро и память:
dmesgпокажет OOM killer и ошибки дисков,vmstat 1покажет своп.
Затем снимок изнутри рантайма: для Java jcmd <PID> Thread.print два или три раза с интервалом в несколько секунд, чтобы увидеть, какие потоки стоят на месте; для Go дамп горутин через /debug/pprof/goroutine?debug=2; для Python py-spy dump --pid <PID>.
В Kubernetes смотрите kubectl describe pod (рестарты по liveness probe, OOMKilled), троттлинг CPU из-за лимита, а внутрь заходите отладочным контейнером через kubectl debug.
Где спотыкаются
Перезапускают сразу. Сервис оживает, а причина исчезает вместе с состоянием процесса. Сначала дампы и метрики, потом рестарт.
Смотрят только на CPU и память хоста. Зависание часто выглядит как простой: процесс ничего не потребляет, потому что ждёт ответа базы или внешнего API без таймаута.
Снимают один дамп потоков. По одному снимку не отличить поток, который долго работает, от потока, который застрял, нужны несколько с интервалом.