#Симптомы и условия возникновения
Node.js может прекратить работу с сообщением «JavaScript heap out of memory» либо быть принудительно завершён системой без ошибки V8. Эти ситуации требуют разной диагностики: лимит кучи, утечка, загрузка больших объектов или предел памяти контейнера. Для начала проверьте используемую версию среды и точный текст ошибки на копии проекта, не меняя рабочий сервер.
#Причины и как их отличить
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Лимит кучи V8В этой ситуации наблюдается конкретный диагностический признак. Сопоставьте его с журналом ошибки и результатом соответствующей проверки, прежде чем выбирать исправление. | В журнале FATAL ERROR: Reached heap limit, рост heapUsed | Собирать профиль потребления и уменьшать размер одновременно удерживаемых данных. |
| Память контейнера или ОСВ этой ситуации наблюдается конкретный диагностический признак. Сопоставьте его с журналом ошибки и результатом соответствующей проверки, прежде чем выбирать исправление. | Процесс завершён SIGKILL/137, нет сообщения V8, наблюдается рост RSS | Смотреть лимиты Docker/cgroup и внешнюю память Buffer. |
| Неограниченное накоплениеВ этой ситуации наблюдается конкретный диагностический признак. Сопоставьте его с журналом ошибки и результатом соответствующей проверки, прежде чем выбирать исправление. | Память растёт при каждом одинаковом запросе и не снижается после паузы | Проверять массивы, кэши, слушатели и очереди. |
#Пошаговая диагностика и решение
- 1. Отличите аварийное завершение V8 от убийства системойОткройте журнал приложения или
docker logsи найдите последние 30–50 строк до остановки. Формулировка heap out of memory указывает на V8; код 137 и сообщение OOMKilled — на ограничение ОС или контейнера. Не повышайте лимит памяти наугад.Linux · Терминал (Bash)КомандаТолько для контейнеров Docker; подставьте его действительное имя. true/137 требует проверки лимитов.docker inspect --format "{{.State.OOMKilled}} {{.State.ExitCode}}" ИМЯ_КОНТЕЙНЕРА
- 2. Измерьте память тем же Node, что запускает сервисВ тестовой копии добавьте вывод process.memoryUsage() каждые 30 секунд.
heapUsed— куча JavaScript,rss— весь процесс,external— внешние объекты. Наблюдайте до и после типичного запроса; не выводите содержимое запросов или секреты.
- 3. Запишите контрольный профильОткройте тестовый каталог проекта; воспроизведите проблему малыми порциями, сохраните несколько измерений через равные интервалы. Если heapUsed каждый раз поднимается, а после отдыха остаётся выше предыдущего уровня, ищите удерживаемые ссылки; если растёт лишь RSS, исследуйте Buffers и нативные пакеты.
- 4. Найдите тяжёлую операциюПроверьте чтение файлов целиком (
readFile),JSON.parseогромных тел, накопление ответов и повторяющиесяsetInterval. Для больших файлов используйте поток; для больших запросов предусмотрите ограничение на размер до разбора JSON.
- 5. Запустите профиль кучи только в изолированной копииСделайте резервную копию журнала и данных тестовой среды. При возможности запустите
node --inspectна локальной машине, откройте Chrome DevTools → Memory, сравните снимки до и после одинаковой нагрузки. Профиль может содержать личные данные и временно увеличивать расход памяти.
- 6. Измените причину, а не только число мегабайтИсправьте накопление, внедрите ограниченный кэш, постраничную обработку и освобождение подписок. Временное увеличение
--max-old-space-sizeобсуждайте лишь после расчёта доступной RAM с учётом ОС и других служб; большая куча не исправляет утечки.
- 7. Сравните повторный прогонНа тестовой среде повторите одинаковое число запросов, сравните
heapUsed,rss, число ошибок и время обработки. При ухудшении верните копию кода; рост памяти без возврата к исходному уровню требует более глубокого профилирования. - Пример кода по темеТекстДобавьте временно в тестовый сервер; удостоверьтесь, что журнал не попадает в публичный доступ.
setInterval(() => { const m = process.memoryUsage(); console.log(Object.fromEntries( Object.entries(m).map(([k, v]) => [k, Math.round(v / 1024 / 1024) + ' MiB']) )); }, 30000).unref();
#Как проверить результат и что делать, если не помогло
Проверка пройдена, если процесс выдерживает прежнюю нагрузку без ошибок кучи или OOMKill, а память стабилизируется. Сохраните графики измерений и предыдущую версию программы для отката.
Если неисправность повторилась, выпишите первый код ошибки и действие, на котором она возвращается. Сравните версию Node.js/npm, рабочий каталог, настройки процесса и журнал тестового запуска. Откатите только внесённые изменения из предварительно сохранённой копии, затем разберите причину на отдельной среде.