Как исправить утечку памяти в ws и socket.io?

Вопрос или проблема

Я прочитал, что существует утечка памяти в модулях WebSocket node.js ws и socket.io. Она существует уже несколько лет, и мне интересно, как это исправить.

Об этом упоминается в следующих источниках, чтобы назвать несколько:

Учитывая, что сейчас 2021 год, является ли установка ключа perMessageDeflate на false и, возможно, предзагрузка jemalloc по-прежнему лучшим решением?

Мое примитивное понимание этой проблемы следующее (не цитируйте меня на это):

  • модуль ws node.js (то есть модуль WebSocket) и модуль socket.io node.js оба используют другой модуль под названием zlib. Этот модуль отвечает за сжатие любых сообщений, когда они отправляются через WebSocket.
  • модуль zlib имел проблему в прошлом, связанную с фрагментацией памяти, которая имитирует утечку памяти (то есть это не настоящая утечка памяти, а фрагментация памяти).
  • сжатие сообщений отключено по умолчанию на сервере, но включено по умолчанию на клиенте (например, в браузере). Если мы отключим это, модуль zlib не будет использован, что устранит проблему с фрагментацией памяти.
  • Чтобы отключить сжатие на клиенте (например, в браузере), мы задаем ключ perMessageDeflate в вашем серверном коде значением false. То есть:

const wss = new WebSocket.Server({ server:httpsServer, perMessageDeflate: false });

Очевидно, это не решение для людей, желающих сжимать свои сообщения. Но стоит упомянуть, что:

  • проблема с фрагментацией памяти в zlib, по-видимому, была ЧАСТИЧНО исправлена с помощью https://github.com/websockets/ws/pull/1204, но, похоже, она все еще присутствует; и
  • польза от сжатия небольших сообщений, таких как короткие тексты, обсуждается. Некоторые даже утверждают, что сжатие небольших сообщений замедляет работу. Если вы работаете с большими данными, такими как изображения или видео, вы можете добиться успеха, сжав их самостоятельно (то есть без ws/socket.io/zlib) перед отправкой через WebSocket.

Также некоторые отметили, что установка perMessageDeflate: false лишь уменьшает проблему, но не решает её полностью. Я бы обратил ваше внимание на это обсуждение, где говорится, что НЕКОТОРОЕ остаточное и постоянное (то есть не увеличивающееся) использование памяти при открытии и закрытии WebSocket является нормальным (я не утверждаю, что это правильно, между прочим): https://github.com/websockets/ws/issues/804#issuecomment-302612661

Что касается предзагрузки jemalloc, похоже, что это не решает проблему. Хотя если указанный выше код не работает, это определенно стоит проверить (или попробовать).

Так является ли preMessageDeflate: false сейчас лучшим решением? Исходя из моего понимания, я бы сказал да.

Если у кого-то есть исправления или дополнительная информация по этому поводу, пожалуйста, добавьте.

Ответ или решение

Как устранить утечку памяти в ws и socket.io

Устранение утечек памяти в модулях Node.js для веб-сокетов, таких как ws и socket.io, остается актуальной проблемой, о которой много говорилось в сообществе разработчиков. В этой статье мы подробно рассмотрим возможные решения, включая настройку параметров сжатия сообщений и использование jemalloc.

Основные причины проблемы

Утечки памяти, замеченные в этих модулях, часто возникают не из-за проблем в самих библиотеках, а скорее из-за особенностей работы с модулем сжатия zlib. С точки зрения архитектуры это можно описать следующим образом:

  1. Модуль zlib: Это стандартный модуль, который отвечает за сжатие данных, передаваемых через веб-сокеты. Его использование может привести к фрагментации памяти.
  2. Конфигурация по умолчанию: Хотя сжатие сообщений отключено на стороне сервера, оно включено для клиентов, что приводит к активному использованию zlib. Это вызывает фрагментацию и, как следствие, растущие требования к памяти.
  3. Предлагаемое решение: Отключение сжатия через настройку perMessageDeflate: false в конфигурации веб-сокета.
const wss = new WebSocket.Server({ server: httpsServer, perMessageDeflate: false });

Это изменение может значительно уменьшить потребление памяти, позволяя избежать фрагментации. Однако важно понимать, что это может не подходить для всех случаев — компрессия данных может быть важной, особенно при передаче больших объемов информации.

Дискуссия по поводу компрессии

Как большинство разработчиков подтвердят, компрессия может быть полезной, но не всегда необходима, особенно для небольших текстовых сообщений. Эффективность сжатия зависит от объема передаваемых данных:

  • Малые сообщения: Сжатие может увеличивать время обработки, так как сжатие и разжатие по сути требует дополнительных ресурсов. В этом случае лучше передавать данные в их нежатом виде.
  • Большие данные: Если вы работаете с крупными файлами, такими как изображения или видео, то стоит рассмотреть возможность предварительного сжатия данных перед передачей через веб-сокет. Это снизит нагрузку на модуль zlib и уменьшит вероятность возникновения проблем с памятью.

Дополнительные решения

  1. Использование jemalloc: Предварительная загрузка jemalloc может помочь в управлении фрагментацией памяти. Однако, данные решения имеют смешанные отзывы по своей эффективности. Некоторые разработчики утверждают, что jemalloc не всегда решает проблему. Тем не менее, если отключение сжатия не помогает, стоит рассмотреть этот вариант.

  2. Постоянный мониторинг: Каждое ваше приложение уникально, и важно постоянно отслеживать его производительность и потребление памяти. Использование инструментов, таких как Node.js heapdump или профайлеры, может помочь выявить и диагностировать утечки.

  3. Альтернативные библиотеки: Воспользуйтесь альтернативными библиотеками или подходами для обработки веб-сокетов, если ваша архитектура это позволяет.

Заключение

По состоянию на 2021 год, основным методом для устранения утечек памяти в ws и socket.io остается установка perMessageDeflate: false. Это простое решение может значительно улучшить производительность и стабильность вашего приложения. Важно помнить, что постоянный мониторинг и адаптация к изменениям в требованиях приложения являются ключевыми моментами в управлении производительностью.

Если у вас есть дополнительные вопросы или предложения по оптимизации, не стесняйтесь делиться своим опытом с сообществом.

Оцените материал
Добавить комментарий

Капча загружается...