我目前在服务器上使用socket.io v1.4.2和node.js v0.10.29。 我尝试在我的应用程序中跟踪内存泄漏,我不确定,但我认为socket.io是我问题的一部分。
所以这里是服务器的代码(演示示例):
var server = require ('http').createServer ();
var io = require ('socket.io')(server);
io.on ("connection", function (socket) {
socket.on ('disconnect', function (data) { /* Do nothing */ });
});
第1步:记忆:58Mb
步骤2:我创建了很多客户端(~10000),内存:300 Mb
第3步:我关闭所有客户并等待GC完成他的工作
第4步:我看看我的记忆:100 Mb:'(
步骤5:与步骤2和3相同
第6步:记忆160Mb ......
等等,内存不断增长。
我认为GC很懒,所以我重试以下代码:
setInterval (function () {
global.gc ();
}, 30000);
我用以下内容启动app.js:
node --expose-gc app.js
但我有同样的结果。
最后我试试
var server = require ('http').createServer ();
var io = require ('socket.io')(server);
clients = {};
io.on ("connection", function (socket) {
clients[socket.id] = socket;
socket.on ('disconnect', function (data) {
delete clients[socket.id];
});
});
我得到了同样的结果。 我怎样才能释放这段记忆?
修改
我直接在主要来源上创建快照。
我使用以下命令安装新模块:
npm install heapdump
我在我的代码中写道:
heapdump = require ('heapdump');
setInterval (function () { heapdump.writeSnapshot (); }, 30000);
程序每30秒执行一次dumpdump,并将其保存在当前目录中。 我用Chrome的模块'profiles'读取了heapdump。
所以,问题可能是socket.io,因为我发现很多字符串没有释放,我用socket发出。 也许我不会以正确的方式写出发射器? 我这样做:
var data1 = [1, 2, 3];
var data2 = [4, 5, 6];
var data3 = [7, 8, 9];
socket.emit ('b', data1, data2, data3);
data1 = [];
data2 = [];
data3 = [];
在我的快照中说该程序保留以下字符串:“b [1,2,3] [4,5,6] [7,8,9]”在我的记忆中,数百万次 我想做什么?
我还做了另一个(也许是愚蠢的?)测试:
var t1 = new Date ();
...
var t2 = new Date ();
var data1 = [1, 2, 3];
var data2 = [4, 5, 6];
var data3 = [7, 8, 9];
socket.emit ('b', data1, data2, data3);
data1 = [];
data2 = [];
data3 = [];
console.log ("LAG: " + t2 - t1);
t1 = new Date ();
我有这个结果:
LAG: 1
LAG: 1
...
LAG: 13
LAG: 2
LAG: 26
LAG: 3
...
LAG: 100
LAG: 10
LAG: 1
LAG: 1
LAG: 120
...
keeps growing
编辑2:
这是我的整个测试代码:
/* Make snapshot every 30s in current directory */
heapdump = require ('heapdump');
setInterval (function () { heapdump.writeSnapshot (); }, 30000);
/* Create server */
var server = require ('http').createServer ();
var io = require ('socket.io')(server);
var t1 = new Date ();
clients = {};
io.on ("connection", function (socket) {
clients[socket.id] = socket;
socket.on ('disconnect', function (data) {
delete clients[socket.id];
});
});
setInterval (function () {
var t2 = new Date ();
for (c in clients) {
var data1 = [1, 2, 3];
var data2 = [4, 5, 6];
var data3 = [7, 8, 9];
clients[c].emit ('b', data1, data2, data3);
data1 = [];
data2 = [];
data3 = [];
}
console.log ("LAG: " + t2 - t1);
t1 = new Date ();
}, 100);
我不提供客户代码。因为我认为:如果问题出在客户端,那么这是一个安全问题。实际上,这将是一种使服务器的RAM饱和的简单方法。所以这是一种更好的DDOS,我希望问题不在客户端。
答案 0 :(得分:1)
根据您收录的服务器代码进行修改
在您的服务器上:
c.emit ('b', data1, data2, data3);`
应更改为:
clients[c].emit('b', data1, data2, data3);
c.emit()
可能会抛出异常,因为c
是socket.id
字符串,字符串不具有.emit()
方法。
原始回答
您需要确定的是内存增长是否实际上是在node.js堆中分配的内存,还是它的空闲内存是否尚未返回到操作系统并且可用于将来在node.js中重用?测量node.js进程使用的内存对于查看它从系统中获取的内容非常有用,并且不应该随着时间的推移不断持续,但它并不能告诉你内部的实际情况。
仅供参考,只要您的node.js应用程序有几个空闲周期,您就不必手动调用GC。它会自己做。
衡量node.js堆中正在使用的内容的常用方法是获取堆快照,运行步骤1-4,获取堆快照,再次运行这些步骤,获取另一个堆快照,区分快照并查看node.js堆中的哪些内存在这两种状态之间实际上是不同的。
这将显示已更改的node.js中实际使用的内容。
这是一篇关于获取堆快照并在调试器中读取它们的文章:https://strongloop.com/strongblog/how-to-heap-snapshots/