p99 вырос в 10 раз, CPU 40%: как ищешь причину
Вопрос
В проде у Node-сервиса p99 латентности вырос с 80 мс до 900 мс, CPU около 40%, база отвечает быстро. Как будете искать причину?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Проверяю задержку 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 ошибок.
Предыдущий вопрос
Что уходит в пул потоков libuv
Следующий вопрос
setImmediate и setTimeout внутри I/O-колбэка
Термины по теме
Ещё по теме «Event loop и libuv»
- Тяжёлый цикл без блокировки event loop
- Код-ревью: что блокирует event loop
- Что блокирует event loop
- Объясни event loop в Node.js
- setImmediate и setTimeout внутри I/O
- setTimeout(0) против setImmediate на верхнем уровне
- Что такое libuv
- Рекурсивный process.nextTick