fs.writeFile在高负载时挂起(v.0.6.6中没有错误)



我们正在努力为尽可能多的请求提供服务,并为每个请求编写一个文件。在小负载情况下可以正常工作,但在高负载情况下,当同步版本仍然正常工作时,异步版本(fs.writeFile)会挂起。节点停止为请求提供服务,并将大多数文件保留为0大小(其中大多数都没有创建)。

v0.6.6 中没有错误

在0.4.7版本中,我们得到了:

{ stack: [Getter/Setter],
arguments: undefined,
type: undefined,
message: 'EMFILE, Too many open files 'aw_1031'',
errno: 24,
code: 'EMFILE',
path: 'aw_1031' }

Ubuntu(VM)和MacOsx中的行为相同。

这是我们当前运行的示例脚本:

ab -n 30000 -c 500 http://HOST:8000/

filetest.js

var http = require('http');
var fs = require('fs');
var util = require ('util');
var i=0;
function writeALot(req, res){
    fs.writeFile("filetest"+i, "Just a try: "+i,
        function(err){
            if(err)    console.log(util.inspect(err));
        });
    i++;
    res.writeHead(200);
    res.end();
}
http.createServer(writeALot).listen(8000);

我们如何管理并发fd的最大数量?有什么建议吗?

提前谢谢。

文件描述符的数量是有限的(http连接也是文件描述符)。在这里,对于每个连接,将编写一个文件,该文件将是500并发的1000个文件描述符。可能你的ulimit -n是1024。实际上,您可以增加限制,我看到有人在生产高并发服务器上这样做。除此之外,您还可以创建一个并发性小于500的队列。我在一个使用async模块的应用程序中做到了这一点。对我提出的每一个要求都加以限制。这将保存我正在创建的文件描述符,但不会保存传入的连接。

var queue = async.queue(function(task, cb) {
    console.log('processing', task.method, queue.length(), task.addr)
    if(task.method === 'file') {
        makeFileStream(task);
    } else {
        makeRequest(task);
    }
}, 500);

稍后,如果我想提出请求或打开文件,

queue.push({
  method : 'file', // or request
  task : 'something'
});

还有这种方式:http://nodebits.org/distilled-patterns

但是,批处理的例子并不像使用队列那样好。

最新更新