Node.JS垃圾收集运行一个小时?

我在这里有一个先前的问题,

有内存泄漏的NodeJS应用程序,它在哪里?

看起来好像是由于VPS的最大内存大小,现在在将VPS内存大小增加到4GB之后,节点JS在GC似乎开始时消耗3.x GB。然后,在GC之前需要约1小时GC至less这就是看起来在服务器监视工具看起来是什么:自由内存达到0,然后约60分钟一个进程运行(CPU负载上升),之后Node.JS应用程序再次发送数据。

这么长的垃圾回收过程是否“正常”? 我错过了什么吗?

这里用一些图来说明:图1:CPU负载1分钟,图2:networking通信量(Mbps),图3:CPU利用率

在这里输入图像描述

对于那些没有遵循上述链接的人来说,这个问题是关于一个使用Pub / Sub和Redis的Node应用程序接收消息,然后发送给所有连接的客户端。

我已经评论了“发送给客户”,内存的增加急剧减慢,使我相信这可能是部分原因,下面是该部分的代码:

nUseDelay=1; .... .... if(nUseDelay>0) { setInterval(function() { Object.getOwnPropertyNames(ablv_last_message).forEach(function(val, idx, array) { io.sockets.emit('ablv', ablv_last_message[val]); }); ablv_last_message= {}; }, 15000*nUseDelay); } 

如果我评论一下:

  // Object.getOwnPropertyNames(ablv_last_message).forEach(function(val, idx, array) { // io.sockets.emit('ablv', ablv_last_message[val]); // }); 

内存增加似乎非常缓慢。 为什么会这样呢? 这是一个所谓的“封闭”,如果是这样,这将如何被理想地logging下来?

在这里完整的代码,这不是一个非常复杂的工作,它在我看来更像一个Node.JS应用程序向所有连接的客户端发送中央应用程序信息的标准框架:

 var nVersion="01.05.00"; var nClients=0; var nUseDelay=1; var ablv_last_message = []; // Production var https = require('https'); var nPort = 6000; // Port of the Redis Server var nHost = "123.123.123.123"; // Host that is running the Redis Server var sPass = "NOT GONNA TELL YA"; var fs = require('fs'); var socketio = require('socket.io'); var redis = require('redis'); // The server options var svrPort = 443; // This is the port of service var svrOptions = { key: fs.readFileSync('/etc/ssl/private/key.key'), cert: fs.readFileSync('/etc/ssl/private/crt.crt'), ca: fs.readFileSync( '/etc/ssl/private/cabundle.crt') }; // Create a Basic server and response var servidor = https.createServer( svrOptions , function( req , res ){ res.writeHead(200); res.end('Hi!'); }); // Create the Socket.io Server over the HTTPS Server io = socketio.listen( servidor ); // Now listen in the specified Port servidor.listen( svrPort ); console.log("Listening for REDIS on " + nHost + ":" + nPort); io.enable('browser client minification'); // send minified client io.enable('browser client etag'); // apply etag caching logic based on version number io.enable('browser client gzip'); // gzip the file io.set('log level', 1); // reduce logging io.set('transports', [ 'websocket' , 'flashsocket' , 'htmlfile' , 'xhr-polling' , 'jsonp-polling' ]); cli_sub = redis.createClient(nPort,nHost); if(sPass != "") { cli_sub.auth(sPass, function() {console.log("Connected!");}); } cli_sub.subscribe("vcx_ablv"); console.log ("Completed to initialize the server. Listening to messages."); io.sockets.on('connection', function (socket) { nClients++; console.log("Number of clients connected " + nClients); socket.on('disconnect', function () { nClients--; console.log("Number of clients remaining " + nClients); }); }); cli_sub.on("message",function(channel,message) { var oo = JSON.parse(message); ablv_last_message[oo[0]["base"]+"_"+oo[0]["alt"]] = message; }); if(nUseDelay>0) { var jj= setInterval(function() { Object.getOwnPropertyNames(ablv_last_message).forEach(function(val, idx, array) { io.sockets.emit('ablv', ablv_last_message[val]); }); ablv_last_message= {}; }, 5000*nUseDelay); } 

在运行应用程序几分钟之后,在这里进行heapdump分析: 在这里输入图像描述

我想我会碰到这个问题,因为还没有给出令人满意的答案。

顺便说一句,我把Node.JS应用程序的NGINX面前,所有的内存问题都消失了,Node应用程序现在稳定在500MB – 1GB左右。

我们最近有同样的问题。

Socket.io v0.9.16每个连接自动打开5个通道,closures它们非常困难。 我们有18个服务器在内存中不断获得内存,直到它冻结,并重新启动服务器。

通过更新到Socket.io v0.9.17,问题就消失了。

我们花了一到三个星期的时间查看每一行代码,find罪魁祸首。