Fuga de memoria al emitir mensajes con Socket.IO+Node.js+ZMQ
sockets memory-leaks (2)
Tengo tres aplicaciones hablando entre sí. Un servidor websocket (1) que acepta conexiones de navegadores, analiza la URL para ver qué datos se requieren, lo envía al cliente si tiene los datos en la memoria, si no lo solicita desde otra aplicación llamada "fetcher" (2). Fetcher recibe este trabajo, lo solicita desde una API simple (3) que devuelve datos JSON, y lo envía de vuelta al servidor websocker que lo publica a los clientes conectados. "Obtención" luego comienza a verificar periódicamente si hay actualizaciones para esa url / trabajo, y envía los nuevos datos al servidor websocket a medida que ocurren.
Yo uso socket.io para la comunicación del servidor cliente-servidor web. El servidor Websocket y el buscador hablan a través de zócalos ZMQ .
Cargué el servidor de websocket de prueba con 130 conexiones . El servidor Websocket publica 160 KB de datos a 130 clientes por segundo. Al principio, usa 170mb de RAM para 130 conexiones, pero rápidamente aumenta a 1GB aunque no hay nuevas conexiones. Entonces, las señales de latido de socket.io comienzan a fallar, lo que provoca la caída de las conexiones.
Yo uso Nodetime para tomar instantáneas de montón. Justo después de que el cliente 130 se conecta, así es como se ve la memoria:
346 objetos Buffer con un total de 44MB .
En cuatro minutos, el número de objetos Buffer aumenta dramáticamente (nuevamente, sin nuevas conexiones): hay 3012 de ellos con una memoria total de 486MB . Después de 10 minutos más, hay 3535 de ellos con un consumo total de memoria de 573MB .
Utilicé el memwatch de Mozilla para descubrir qué línea agrega a la memoria, y encontré esta función:
function notifyObservers(resourceId) {
var data = resourceData[resourceId];
io.sockets.in(resourceId).emit(''data'', data);
}
Si comento estas líneas, el uso de la memoria se mantiene igual, eso es otra confirmación.
¿Alguna idea de cómo puede pasar esto? Llamo a esta función dentro del método del zócalo del suscriptor de ZMQ y sospecho que tiene algo que ver con eso ... Este es el código resultante si elimino funciones y las fusiono en una:
// 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]);
});
Todo mi código (incluida la prueba de carga) es público y puede encontrar este servidor de conexión web aquí: https://github.com/denizozger/node-socketio/blob/master/server.js Consulte la línea 138.
Empecé a aprender Javascript y Node.js hace dos meses, así que cualquier comentario es bienvenido, ¡gracias de antemano!
NodeJs puede ser el uso de Windows Socket API (que incluyen pérdidas de memoria, antiguo error conocido) https://connect.microsoft.com/VisualStudio/feedback/details/605621/winsock-c-program-causes-memory-leak
El problema es que nunca se llamará WSACleanup hasta que cierre los servicios de red. (Mezclar ZMq o Nodejs no cambiará ese hecho)
Ahora, con el tiempo, bloqueará más páginas de memoria y tal aviso aumentará una vez que la primera página de memoria esté llena.
tal vez intente agregar
var resourceData;
en algún lugar de su código porque tal vez su fuga de memoria tiene que ver con globales
lea más acerca de los globales aquí: https://gist.github.com/hallettj/64478