ENOMEM в Node.js, вызванный высоким использованием виртуальной памяти

Я получаю ошибки ENOMEM в моем рабочем приложении Node.js (v12) в течение нескольких месяцев.

Эту проблему было особенно сложно диагностировать, потому что размер моей кучи всегда находится в диапазоне 100 МБ и со временем не увеличивается. Следовательно, утечка памяти узла маловероятна.

Однако иногда использование памяти VIRT (как сообщает top cmd) достигает 15-20 ГБ, и именно тогда узел начинает выдавать некоторые ошибки "spawn: enomem".

Насколько я понимаю, что-то заставляет узел зарезервировать много-много виртуальной памяти, хотя размер кучи стабильно составляет 100 МБ. И я не могу диагностировать, что это такое, поскольку инструменты дебюта узлов позволяют мне только проверять кучу.

Я потратил около 100 часов на эту проблему, поэтому я буду благодарен за любую информацию / помощь!

Я попытался:

  • Ручная установка --max-old-space-size
  • Увеличение оперативной памяти на сервере
  • Добавление SWAP на мой сервер и разрешение докеру использовать этот SWAP
  • Проверка кучи узлов с помощью инструментов chrome dev
  • Установка лимита памяти для моих контейнеров докеров
  • Переход к другому менеджеру процессов (pm2 вместо supervisord)
  • обновление всех моих пакетов и использование последней LTS-версии узла
  • Чтение и понимание всех результатов Google для узла ENOMEM
  • Понимание того, как Node управляет своим пулом памяти, особенно в отношении кучи и GC.
  • Погружение в концепции ядра Linux о виртуальной, зарезервированной, подкачиваемой и общей памяти.

Спасибо за вашу помощь!

1 ответ

Нам удалось решить проблему. Имейте в виду, что решение может быть специфическим для нашего собственного проекта.

Нам удается последовательно воспроизвести ошибку при использовании пакета "imagemin" с "imagemin-jpegtran" и "imagemin-pngquant" на большом массиве (20 КБ +) файлов и ожидании завершения всех обещаний с помощью prom.all (). Использование памяти VIRT увеличилось до 20 ГБ + и никогда не освобождалось после выполнения.

Решением для нас было использование plimit, чтобы ограничить количество одновременных обещаний до 5 или 10. На том же количестве изображений (20k+) использование памяти VIRT никогда не увеличивалось, равно как и RES, и мы перестали получать ошибки ENOMEM.

Надеюсь, это поможет кому-то там

Другие вопросы по тегам