Подтвердить что ты не робот

Утечка памяти при испускании сообщений с помощью Socket.IO + Node.js + ZMQ

У меня есть три приложения, разговаривающие друг с другом. Сервер websocket (1), который принимает соединения из браузеров, анализирует URL-адрес, чтобы узнать, какие данные необходимы, обслуживает его для клиента, если он имеет данные в памяти, если не запрашивает его из другого приложения, называемого "fetcher" (2). Fetcher получает это задание, запрашивает его из простого API (3), который возвращает данные JSON и отправляет его обратно на сервер websocker, который публикует его для подключенных клиентов. Затем "Fetcher" начинает периодически проверять, есть ли обновления для этого url/job, и отправляет новые данные на сервер websocket по мере их возникновения.

Я использую socket.io для связи с сервером client-websocket. Сервер веб-сервера и сборщик взаимодействуют через сокеты ZMQ.

Я загружаю тестовый сервер websocket с 130 соединениями. Сервер Websocket ежемесячно издает 160 Кбайт данных 130 клиентам. Вначале он использует 170 МБ ОЗУ для 130 подключений, но быстро это увеличивается до 1 ГБ, хотя новых подключений нет. Затем сигналы heartbeat socket.io начинают сбой, что приводит к сброшенным соединениям.

Я использую Nodetime для получения снимков кучи. Сразу после подключения 130-го клиента, как выглядит память:

enter image description here

346 Буферные объекты с общим 44 МБ.

За четыре минуты количество объектов буфера резко возрастает (опять же, без новых подключений): из них 3012 с общей памятью 486 МБ. Через 10 минут из них 3535 из них имеют общий объем памяти 573 МБ.

Я использовал Mozilla memwatch, чтобы узнать, какая строка добавляется в память, и обнаружила, что эта функция:

function notifyObservers(resourceId) {
  var data = resourceData[resourceId];
  io.sockets.in(resourceId).emit('data', data);
}

Если я прокомментирую эти строки, использование памяти останется таким же, что и другое подтверждение.

Любые идеи, как это может произойти? Я вызываю эту функцию внутри метода сокета абонента ZMQ, и я подозреваю, что это имеет какое-то отношение к этому. Это результирующий код, если я удаляю функции и объединяю их в один:

// Receive new resource data
const resourceUpdatedSubscriber = zmq.socket('sub').connect('tcp://localhost:5433');
resourceUpdatedSubscriber.subscribe('');

resourceUpdatedSubscriber.on('message', function (data) {
  var resource = JSON.parse(data);

  resourceData[resource.id] = resource.data;

  io.sockets.in(resourceId).emit('data', resourceData[resource.id]);
});

Весь мой код (включая тест нагрузки) является общедоступным, и здесь вы можете найти этот сервер веб-сокетов: https://github.com/denizozger/node-socketio/blob/master/server.js См. строку 138.

Я начал изучать Javascript и Node.js два месяца назад, поэтому любые комментарии приветствуются, спасибо заранее!

4b9b3361

Ответ 1

NodeJs может использовать API Windows Socket (который включает утечки памяти, старую известную ошибку) https://connect.microsoft.com/VisualStudio/feedback/details/605621/winsock-c-program-causes-memory-leak

Проблема заключается в том, что WSACleanup никогда не будет вызываться до тех пор, пока вы не отключите сетевые службы. (Смешение ZMq или Nodejs не изменит этого факта)

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

Ответ 2

возможно, попробуйте добавить

var resourceData;

где-то в вашем коде, потому что, возможно, утечка памяти связана с глобальными

Узнайте больше о глобальных шагах: https://gist.github.com/hallettj/64478