Ответ вслух Senior Event loop и libuv обновлено

p99 вырос в 10 раз, CPU 40%: как ищешь причину

Вопрос

В проде у Node-сервиса p99 латентности вырос с 80 мс до 900 мс, CPU около 40%, база отвечает быстро. Как будете искать причину?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Высокий p99 при невысоком CPU почти всегда значит ожидание, а не нехватку мощности. В Node первое подозрение: основной поток блокируется синхронной работой, и все запросы ждут в очереди.

Что должно прозвучать в ответе

  • Проверяю задержку event loop (`monitorEventLoopDelay`, метрика `nodejs_eventloop_lag` в prom-client): высокая значит синхронная работа в основном потоке

  • Снимаю CPU-профиль под нагрузкой (`--cpu-prof`, `inspector`, clinic flame) и ищу широкие синхронные функции: JSON, regex, sync crypto/fs

  • Смотрю GC: паузы и рост heap (`--trace-gc`, метрики heap), утечка памяти даёт частые полные сборки

  • Проверяю насыщение пула libuv (fs, dns.lookup, crypto) и пулов соединений (БД, HTTP agent `maxSockets`)

  • Сверяю с деплоями и трафиком: что изменилось, какие эндпоинты медленные (трейсы), воспроизвожу нагрузочным тестом

  • Фикс по причине: вынести CPU в worker_threads, кеш, пагинация, увеличить пул, и метрика как регрессионный алерт

Что могут спросить следом

  • Чем задержка event loop отличается от загрузки CPU?
  • Как снять профиль с работающего пода без перезапуска?
  • Почему средняя латентность могла не измениться?

Разбор

Высокий p99 при невысоком CPU почти всегда значит ожидание, а не нехватку мощности. В Node первое подозрение: основной поток блокируется синхронной работой, и все запросы ждут в очереди. Это видно по задержке event loop: perf_hooks.monitorEventLoopDelay или готовая метрика в prom-client. Если она высокая, снимаю CPU-профиль под нагрузкой (node --cpu-prof или через inspector на живом процессе) и ищу широкие синхронные функции: разбор большого JSON, регулярку с бэктрекингом, *Sync-вызовы, сортировку огромного массива. Если event loop в порядке, проверяю GC (рост heap и паузы на полную сборку при утечке), затем насыщение пулов: libuv (fs, dns.lookup, crypto), пул соединений к БД, maxSockets HTTP-агента. Все гипотезы сверяю с трейсами по эндпоинтам и с тем, что менялось в релизе. Исправление зависит от причины, а метрику лага оставляю алертом.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме