我们正在努力为尽可能多的请求提供服务,并为每个请求编写一个文件。在小负载情况下可以正常工作,但在高负载情况下,当同步版本仍然正常工作时,异步版本(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
但是,批处理的例子并不像使用队列那样好。