Node.JS垃圾收集运行一小时?
我有一个关于赏金的问题: 看起来这似乎是由于VPS的最大内存大小,现在将VPS内存大小增加到4GB后,当GC开始工作时,节点JS消耗3.x GB。然后,在节点再次响应之前,GC需要约1个小时,至少从服务器监视工具来看是这样的: 空闲内存达到0,然后一个进程运行约60分钟(CPU负载上升),然后Node.JS应用程序再次发送数据 这么长的垃圾收集过程“正常”吗?我错过什么了吗 这里有一些图来说明它:图1:CPU负载1分钟,图2:网络流量(以Mbps为单位),图3:CPU利用率 对于那些没有遵循上面链接的人来说,这个问题是关于一个节点应用程序,它使用带有Redis的Pub/Sub来接收消息,然后发送给所有连接的客户端 我已经注释掉了“发送到客户端”,内存增长急剧放缓,使我相信这可能是部分原因,下面是该部分的代码:Node.JS垃圾收集运行一小时?,node.js,Node.js,我有一个关于赏金的问题: 看起来这似乎是由于VPS的最大内存大小,现在将VPS内存大小增加到4GB后,当GC开始工作时,节点JS消耗3.x GB。然后,在节点再次响应之前,GC需要约1个小时,至少从服务器监视工具来看是这样的: 空闲内存达到0,然后一个进程运行约60分钟(CPU负载上升),然后Node.JS应用程序再次发送数据 这么长的垃圾收集过程“正常”吗?我错过什么了吗 这里有一些图来说明它:图1:CPU负载1分钟,图2:网络流量(以Mbps为单位),图3:CPU利用率 对于那些没有遵循
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]);
// });
记忆增长似乎非常缓慢。这是为什么呢?这是所谓的“结束”吗?如果是这样,理想情况下如何重新编码
这里是完整的代码,这不是一项非常复杂的工作,在我看来,它更像是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分析:
我想我会问这个问题,因为还没有令人满意的答案
顺便说一句,我将NGINX放在Node.JS应用程序前面,所有内存问题都解决了,节点应用程序现在的容量约为500MB-1GB。我们最近遇到了同样的问题 Socket.io v0.9.16每个连接自动打开5个通道,并且很难关闭它们。我们有18台服务器在运行,它们的内存不断增加,直到它冻结,然后重新启动服务器 通过更新到Socket.io v0.9.17,问题消失了
我们花了一到三周的时间检查每一行代码,以找到罪犯。听起来不正常。看看前面的问题,我想知道如果节点占用1.6到2GB的内存,您要处理多少连接的客户端。必须是巨大的(这和/或消息是巨大的)。另外,内存需要多长时间才能被填满?在平均2500个连接的客户端中,目前的峰值为3500个。我每5秒钟向客户端发送一次更新,我的服务器显示出约10Mbps到15Mbps的出站带宽。这是一个不错的数字,但听起来仍然有内存泄漏,2500个客户端的2GB容量仍然相当高。我想我将在这里“开源”整个代码。看起来是解决这个问题的唯一方法。也许您可以使用原始代码生成一些堆快照,看看这是否有助于了解泄漏的内容。