lmq*_*kfh 5 memory-leaks node.js socket.io
我目前在我的服务器上使用 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 */ });
});
Run Code Online (Sandbox Code Playgroud)
第 1 步:内存:58Mb
第 2 步:我创建了很多客户端(~10000),内存:300 Mb
第 3 步:我关闭所有客户端并等待 GC 完成他的工作
第 4 步:我查看我的内存:100 Mb :'(
第 5 步:与第 2 步和第 3 步相同
第 6 步:内存 160Mb...
依此类推,内存不断增长。
我认为 GC 是懒惰的,所以我使用以下代码重试:
setInterval (function () {
global.gc ();
}, 30000);
Run Code Online (Sandbox Code Playgroud)
我用以下命令启动我的 app.js:
node --expose-gc app.js
Run Code Online (Sandbox Code Playgroud)
但我得到了同样的结果。
最后我尝试
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];
});
});
Run Code Online (Sandbox Code Playgroud)
我得到了同样的结果。我怎样才能释放这个内存?
编辑
我直接在我的主要来源上创建快照。
我使用以下命令安装新模块:
npm install heapdump
Run Code Online (Sandbox Code Playgroud)
我在我的代码中这样写:
heapdump = require ('heapdump');
setInterval (function () { heapdump.writeSnapshot (); }, 30000);
Run Code Online (Sandbox Code Playgroud)
它每 30 秒对程序进行一次 heapdump,并将其保存在当前目录中。我使用 Chrome 的模块“配置文件”读取了堆转储。
所以,问题可能是 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 = [];
Run Code Online (Sandbox Code Playgroud)
在我的快照中说程序保留了以下字符串:“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 ();
Run Code Online (Sandbox Code Playgroud)
我有这个结果:
LAG: 1
LAG: 1
...
LAG: 13
LAG: 2
LAG: 26
LAG: 3
...
LAG: 100
LAG: 10
LAG: 1
LAG: 1
LAG: 120
...
keeps growing
Run Code Online (Sandbox Code Playgroud)
编辑 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);
Run Code Online (Sandbox Code Playgroud)
我不给客户代码。因为我认为:如果问题出在客户端,那么这是一个安全问题。事实上,这将是一种使服务器 RAM 饱和的简单方法。所以这是一种更好的 DDOS,我只是希望问题不在客户端。
根据您包含的服务器代码进行编辑
在您的服务器上:
c.emit ('b', data1, data2, data3);`
Run Code Online (Sandbox Code Playgroud)
应改为:
clients[c].emit('b', data1, data2, data3);
Run Code Online (Sandbox Code Playgroud)
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/
| 归档时间: |
|
| 查看次数: |
3759 次 |
| 最近记录: |