У меня есть три приложения, разговаривающие друг с другом. Сервер 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-го клиента, как выглядит память:
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 два месяца назад, поэтому любые комментарии приветствуются, спасибо заранее!