1

I'm using websockets to transfer video files, this means they are large files. The server side (and also the client side) is implemented using nodejs, with binaryjs in javascript.

It worked fine, until I started having a great number of clients, what made the server crash (process was killed by Linux OS). As I observed, it ran out of memory, since for every client it's taking a lot of it, but the thing is that when the client disconnects this memory is not freed. I think this should be done internally and that I should not worry about memory, am I wrong? may I be doing something wrong?

As I've seen, that "send" function is reserving memory to save what it has to send but never frees it. (If you comment that line, there's no memory problem) Here's the code:

var fs = require('fs');
var BinaryServer = require('binaryjs').BinaryServer;
var bs = BinaryServer({port: 8080});

var nchunks=116;

bs.on('connection', function(client){
for(var i=1; i<=nchunks; i++)
{
    var name="/var/www/1.m4s";
    var fd=fs.openSync(name.replace("1.m4s", i+".m4s"), 'r');
    var buf = new Buffer(fs.fstatSync(fd).size, 'binary');
    fs.readSync(fd, buf, 0, buf.length, null)
    client.send(buf);
    fs.closeSync(fd);

    if(i==nchunks){
        client.send("end"); 
    }
}
client.on('close', function(c){
    console.log("closing");
});

});

When the clients receives all of the video files, closes the socket, so I know it's getting closed since I'm capturing "close" event on server. Shouldn't it at this moment free the memory?

The worst thing is, as I couldn't find the error, I thought it might be due to how binaryjs implements it so I tried also with "ws" and "websocket-node" with same results in the memory.

Has anyone experienced this problems? Any idea?

4

1 回答 1

2

难道此时不应该释放内存

不,JavaScript 是一种垃圾收集语言,垃圾收集器会在运行时认为合适的时候定期运行。您无法控制或知道它何时或是否会运行并因此释放内存。

此外,您不能在网络服务器中使用任何同步 IO 调用,因为在您执行每个 IO 调用时,所有客户端处理都会阻塞。

我认为你的主要问题是你没有以相当小的块流式传输文件。您正在尝试将整个文件读入内存并将它们发送下来。

var buf = new Buffer(fs.fstatSync(fd).size, 'binary');

不要那样做。使用 ReadableStream 并以一系列小块向下发送文件,并使用异步调用。这是让节点为您正常工作的方法。缺乏流式传输和缺乏异步调用肯定是节点失败的路径。这是一个工作示例程序。

var fs = require("fs");
var http = require("http");
var server = http.createServer();
server.listen(9200)
server.on('request', function (req, res) {
  fs.createReadStream('/tmp/test1').pipe(res);
});

我在 OSX 上使用节点 v0.10.7 对此进行了测试,我可以反复请求文件curl localhost:9200 >/dev/null并观察lsof -p <pid of node>我可以看到/tmp/test文件被正确打开和关闭。

于 2013-05-23T22:02:30.190 回答