Ответ вслух Senior Кластер, воркеры, масштабирование обновлено

Утечка памяти в проде: план действий

Вопрос

Память Node-сервиса медленно растёт, через сутки под убивается по OOM. Как найдёте утечку?

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

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

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

Коротко

Сначала убеждаюсь, что это утечка heap: смотрю heapUsed после полных сборок мусора. Если растёт только RSS, а heap стабилен, искать надо в буферах, нативных модулях или фрагментации.

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

  • Подтверждаю по метрикам: растёт именно heap (`heapUsed`) после полных GC, а не RSS из-за буферов или нативных модулей

  • Снимаю несколько heap snapshot с интервалом (`--heapsnapshot-signal`, inspector, `v8.writeHeapSnapshot`) и сравниваю: какие объекты растут и кто их держит (retainers)

  • Типичные причины: кеш без лимита и TTL, Map по id запросов, слушатели событий без отписки, замыкания в таймерах, глобальные массивы

  • Учитываю, что снимок останавливает процесс и требует памяти: снимаю на выведенной из балансировки реплике

  • Воспроизвожу нагрузкой локально или на стейдже, фикс подтверждаю графиком памяти

  • Временная мера: лимит памяти и рестарт по порогу, но это не решение

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

  • Чем RSS отличается от heapUsed?
  • Почему --max-old-space-size не лечит утечку?
  • Как найти утечку слушателей событий?

Разбор

Сначала убеждаюсь, что это утечка heap: смотрю heapUsed после полных сборок мусора. Если растёт только RSS, а heap стабилен, искать надо в буферах, нативных модулях или фрагментации. Если растёт heap, снимаю два-три heap snapshot с интервалом под нагрузкой: в Node можно запустить с --heapsnapshot-signal=SIGUSR2 или вызвать v8.writeHeapSnapshot(). В Chrome DevTools сравниваю снимки, смотрю, какие конструкторы растут, и по цепочке retainers вижу, кто держит объекты. Чаще всего это кеш без ограничения, Map, в которую кладут по запросу и не удаляют, слушатели событий без off, таймеры с замыканиями на большие объекты. Снимок тяжёлый: он останавливает процесс и временно требует памяти, поэтому делаю его на реплике, выведенной из балансировки. После фикса подтверждаю по графику памяти. Рестарт по лимиту памяти держу как страховку, но это не решение.

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

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

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