Какой план действий при перегрузке CPU и срабатывании алерта
Что проверяют
Есть ли у вас порядок действий под давлением: сначала сохранить сервис, потом разбираться. И умеете ли вы снять профиль Go-сервиса на проде. Следом обычно спрашивают, как понять, что CPU съедает сборщик мусора, а не ваш код.
Как отвечать
Стройте ответ по шагам дежурного:
- оценка влияния: страдают ли пользователи. Смотрите латентность и долю ошибок, а не только процент CPU. Высокая загрузка при нормальном p99 это повод разобраться, но не пожар;
- локализация: один под или все, с какого момента, совпадает ли с релизом, ростом трафика, запуском фоновой задачи;
- смягчение: откат релиза, масштабирование, ограничение входящего трафика, выключение фича-флага;
- улики до перезапуска: CPU-профиль через
net/http/pprof, напримерgo tool pprof http://host:6060/debug/pprof/profile?seconds=30, и дамп горутин/debug/pprof/goroutine?debug=2; - разбор профиля:
top,list, flame graph в веб-интерфейсеpprof. Типичные находки: горячий цикл,regexp.MustCompileна каждый запрос, тяжёлая сериализация JSON, лишние аллокации.
Отдельно проверьте сборщик мусора: заметная доля runtime.gcBgMarkWorker и mallocgc в профиле, метрика go_gc_duration_seconds, трассировка GODEBUG=gctrace=1. Лечится снижением аллокаций, sync.Pool, настройкой GOGC и GOMEMLIMIT.
В контейнере сверьте GOMAXPROCS с лимитом CPU, иначе сервис упирается в троттлинг cgroup (container_cpu_cfs_throttled_seconds_total). Начиная с Go 1.25 рантайм сам учитывает лимит контейнера, раньше для этого ставили automaxprocs.
После инцидента: постмортем, бенчмарк на найденное место, непрерывное профилирование (Pyroscope, Parca).
Где спотыкаются
Сразу перезапускают под. Нагрузка уходит, профиля нет, через сутки всё повторяется.
Смотрят только на процент CPU и не замечают троттлинг: сервис тормозит при средней загрузке 60%, потому что исчерпал квоту cgroup.
Открывают pprof на публичном порту. Эндпоинт должен жить на отдельном внутреннем порту, иначе это утечка данных и лёгкий способ нагрузить сервис.