简体   繁体   English

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

[英]Memory Leak with socket.io + node.js

I appear to have a memory leak with my Node.js application. 我的Node.js应用程序似乎有内存泄漏。 I built it quickly, and my JavaScript isn't too strong, so this might be easy. 我快速构建它,我的JavaScript不是太强大,所以这可能很容易。

I've done some heap dumps on it, and it's the String object ? 我在它上面做了一些堆转储,它是String object leaking memory, at the rate of about 1MB every 5 minutes. 泄漏记忆,每5分钟约1MB。 I expanded String, and it's actually String.Array? 我扩展了String,它实际上是String.Array?

Heap stack: 堆栈: 在此输入图像描述

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

Current version 当前版本

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

Still leaking memory, but it seems only on these conditions: 仍在泄露记忆,但似乎只是在这些条件下:

  • From startup, with no clients -> Fine 从启动,没有客户 - >好
  • 1st client connection -> Fine 第一个客户端连接 - >好
  • 2nd client (even with the 1st client disconnecting and reconnecting) -> Leaking memory 第二个客户端(即使第一个客户端断开连接并重新连接) - >内存泄漏
  • Stop all connections -> Fine 停止所有连接 - >好
  • 1 new connection (connections = 1) -> Leaking memory 1个新连接(连接= 1) - >内存泄漏

Do yourself a favour and use node-mysql , it's a pure javascript mysql client and it's fast. 帮自己一个忙,并使用node-mysql ,它是一个纯粹的javascript mysql客户端,速度很快。 Other than that, you should be using asynchronous code to stop IO being blocked whilst you're working. 除此之外,您应该使用异步代码来阻止IO在您工作时被阻止。 Using the async library will help you here. 使用异步库将在这里帮助您。 It has code for waterfall callback passing among other things. 它有瀑布回调传递的代码和其他东西。

As for your memory leaking, it probably isn't socket.io, although I haven't used it in a few months, I have had many thousands of concurrent connections and not leaked memory, and my code wasn't the best either. 至于你的内存泄漏,它可能不是socket.io,虽然我几个月没有使用它,我有成千上万的并发连接而没有泄漏内存,我的代码也不是最好的。

Two things, however. 然而,有两件事。 Firstly your code is faily unreadable. 首先,你的代码很快就不可读了。 I suggest looking into properly formatting your code (I use two spaces for every indentation but some people use four). 我建议考虑正确格式化你的代码(我为每个缩进使用两个空格,但有些人使用四个)。 Secondly, printing the number of connections every half an hour seems a little silly, when you could do something like: 其次,每半个小时打印一次连接数似乎有点傻,当你可以这样做时:

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

The \\r will cause the line to be read back to the start of the line and overwrite the characters there, which will replace the line and not create a huge amount of scrollback. \\r将导致行被读回到行的开头并覆盖那里的字符,这将替换该行而不会创建大量的回滚。 This will help with debugging if you choose to put debugging details in your logging. 如果您选择在日志记录中添加调试详细信息,这将有助于调试。

You can also use process.memoryUsage() for quickly checking the memory usage (or how much node thinks you're using). 您还可以使用process.memoryUsage()快速检查内存使用情况(或节点认为您正在使用的节点数)。

Could this be related to the connected clients array not clearing properly when a client disconnects? 当客户端断开连接时,这是否与连接的客户端阵列无法正常清除有关? The array value gets set to NULL rather than being dropped from the array. 数组值设置为NULL而不是从数组中删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM