内存泄漏与socket.io + node.js

时间:2011-06-24 16:31:19

标签: javascript node.js socket.io

我的Node.js应用程序似乎有内存泄漏。我快速构建它,我的JavaScript不是太强大,所以这可能很容易。

我已经对它做了一些堆转储,它是字符串object?泄漏记忆,每5分钟约1MB。我扩展了String,它实际上是String.Array?

堆栈: enter image description here

#!/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);
  });

当前版本

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;
            });
    }
}

仍在泄露记忆,但似乎只是在这些情况下:

  • 从创业开始,没有客户 - >细
  • 第一个客户端连接 - >细
  • 第二个客户端(即使第一个客户端断开连接并重新连接) - >泄漏记忆
  • 停止所有连接 - >细
  • 1个新连接(连接= 1) - >泄漏记忆

2 个答案:

答案 0 :(得分:5)

帮自己一个忙,并使用node-mysql,它是一个纯粹的javascript mysql客户端,速度很快。除此之外,您应该使用异步代码来阻止IO在您工作时被阻止。使用async库可以帮助您。它包含瀑布回调传递的代码。

至于你的内存泄漏,它可能不是socket.io,虽然我几个月没有使用它,我已经有成千上万的并发连接而且没有泄漏内存,我的代码不是最好的。

然而,有两件事。首先,你的代码很快就不可读了。我建议考虑正确格式化你的代码(我为每个缩进使用两个空格,但有些人使用四个)。其次,每半个小时打印一次连接数似乎有点傻,当你可以这样做时:

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

\r将导致行被读回到行的开头并覆盖那里的字符,这将替换该行而不会创建大量的回滚。如果您选择在日志记录中添加调试详细信息,这将有助于调试。

您还可以使用process.memoryUsage()快速检查内存使用情况(或节点认为您正在使用的数量)。

答案 1 :(得分:0)

当客户端断开连接时,这是否与连接的客户端阵列无法正常清除有关?数组值设置为NULL而不是从数组中删除。