Pregunta Memory Leak con socket.io + node.js


Parece que tengo una pérdida de memoria con mi aplicación de nodo. Lo construí rápidamente, y mi JavaScript no es demasiado fuerte, así que esto podría ser fácil.

He hecho algunos volcados del montón, ¿y es el 'objeto' String? filtración de memoria, a razón de aproximadamente 1 MB cada 5 minutos. Expandí String, y en realidad es String.Array?

Pila de montón: http://i.imgur.com/ZaBp0.png

#!/usr/local/bin/node

var port = 8081;

var io = require('socket.io').listen(port),
sys = require('sys'),
daemon = require('daemon'),
mysql = require('mysql-libmysqlclient');

var updateq = "SELECT 1=1";
var countq = "SELECT 2=2";

io.set('log level', 2);


process.on('uncaughtException', function(err) {
  console.log(err);
});

var connections = 0;

var conn = mysql.createConnectionSync();
dbconnect();

io.sockets.on('connection', function(client){ 
  connections++;
  client.on('disconnect', function(){ connections--;  }) 
});

process.on('exit', function () {
    console.log('Exiting');
    dbdisconnect();
});

function dbdisconnect() {
     conn.closeSync();
}

function dbconnect() {
    conn.connectSync('leet.hacker.org','user','password');
}


function update() {
    if (connections == 0)
        return;
    conn.query(updateq, function (err, res) {
      if (err) {
        dbdisconnect();
        dbconnect();
        return;
      }
      res.fetchAll(function (err, rows) {
        if (err) {
          throw err;
        }
        io.sockets.json.send(rows);
      });
    });
}

function totals() {
    if (connections == 0)
        return;
        conn.query(countq, function (err, res) {
          if (err) {
        // Chances are that the server has just disconnected, lets try reconnecting
        dbdisconnect();
        dbconnect();
            throw err;
          }
          res.fetchAll(function (err, rows) {
            if (err) {
              throw err;
            }
        io.sockets.json.send(rows);
          });
        });

}

setInterval(update, 250);
setInterval(totals,1000);

setInterval(function() {
console.log("Number of connections: " + connections);
},1800000);



  daemon.daemonize('/var/log/epiclog.log', '/var/run/mything.pid', function (err, pid) {
    // We are now in the daemon process
    if (err) return sys.puts('Error starting daemon: ' + err);

    sys.puts('Daemon started successfully with pid: ' + pid);
  });

Versión actual

function totals() {

        if (connections > 0)
        {
                var q = "SELECT query FROM table";

            db.query(q, function (err, results, fields) {
            if (err) {
                    console.error(err);
                    return false;
            }

            for (var row in results)
            {
                    io.sockets.send("{ ID: '" + results[row].ID + "', event: '" + results[row].event + "', free: '" + results[row].free + "', total: '" + results[row].total + "', state: '" + results[row]$
                    row = null;
            }


            results = null;
            fields = null;
            err = null;
            q = null;
            });
    }
}

Todavía está perdiendo memoria, pero parece solo en estas condiciones:

  • Desde el inicio, sin clientes -> Bien
  • Primera conexión con el cliente -> Bien
  • Segundo cliente (incluso con el primer cliente desconectándose y reconectando) -> Fugas de memoria
  • Detener todas las conexiones -> Bien
  • 1 nueva conexión (conexiones = 1) -> Fugas de memoria

32
2018-06-24 16:31


origen


Respuestas:


Hazte un favor y usa node-mysql, es un cliente javascript mysql puro y es rápido. Aparte de eso, deberías estar usando un código asíncrono para evitar que IO se bloquee mientras trabajas. Utilizando el asincrónico la biblioteca te ayudará aquí. Tiene un código para pasar la devolución de llamada en cascada, entre otras cosas.

En cuanto a su fuga de memoria, probablemente no es socket.io, aunque yo no lo he usado en unos pocos meses, he tenido muchos miles de conexiones simultáneas y no filtrada memoria, y mi código no era la mejor.

Dos cosas, sin embargo. En primer lugar, su código es ilegible. Sugiero buscar el formato correcto de tu código (uso dos espacios para cada sangrado, pero algunas personas usan cuatro). En segundo lugar, imprimir el número de conexiones cada media hora parece un poco tonto, cuando puedes hacer algo como:

setInterval(function() {
  process.stdout.write('Current connections: ' + connections + '     \r');
}, 1000);

los \r hará que la línea para ser leído de nuevo al comienzo de la línea y sobrescribir los caracteres allí, que sustituirá a la línea y no crear una gran cantidad de desplazamiento hacia atrás. Esto ayudará con la depuración si elige poner detalles de depuración en su registro.

También puedes usar process.memoryUsage() para verificar rápidamente el uso de memoria (o la cantidad de nodos que piensa que está usando).


5
2017-07-07 11:02



¿Podría estar esto relacionado con la matriz de clientes conectados que no se borra correctamente cuando un cliente se desconecta? El valor de matriz se establece en NULL en lugar de eliminarse de la matriz.


0
2018-05-02 19:46