所以,我有一个相当大的文件目录,我需要在NodeJS应用程序中使用长时间运行的进程不断处理。该目录正在不断处理和清空,但1000个文件在任何给定时间排队处理并不罕见 - 它们是gzip压缩的CSV文件,所以我天真的解决方案是获取目录列表,迭代文件,打开每个,解析它们,然后继续,像这样:
files = fs.readdirSync 'directory'
for filename in files
file_path = path.resolve path.join 'directory', filename
fd = fs.openSync file_path, 'r'
buf = new Buffer fs.statSync(file_path).size
fs.readSync fd, buf, 0, len, 0
fs.closeSync fd
zlib.gunzip buf, (err, buf) =>
throw err if err
content = buf.toString().split("\n")
for line in content
# parse, process content, archive file
我正在快速遇到EMFILE(Too Many Open Files)错误。请原谅fs函数的同步版本和coffeescript。
有没有更好的方法以托管方式处理大量文件?最后,我想使用类似于单个解析流的东西 - 我知道如何使用单个大型(或甚至不断增长的)文件,但不能使用一个充满单独文件的目录。
这些文件由大量不同的客户端生成到面向公众的Web服务器,然后通过安全协议将它们定期同步到我的输入目录。不是理想的设置,但考虑到系统的特定性质,这是必要的,它解释了为什么我不能简单地改变文件,即单个多路复用流。
答案 0 :(得分:1)
不完全是解析流,但可能是迈向它的一步:
您可以使用https://npmjs.org/package/generic-pool来限制正在处理的并发文件数。您只需要定义要合并的资源。
在您的情况下,我假设要汇总的资源应该是文件处理器,这样一次只能有一个或几个可以存在。
您还可以使用某种迭代器方法来简化下一个要处理的文件。
编辑:完成我的回答。我找到了你的问题并试了一下 https://gist.github.com/Floby/5064222答案 1 :(得分:0)
Mixu的Node书有一节介绍如何正确管理这类问题。 http://book.mixu.net/node/ch7.html
您可以使用以下代码在“有限并行”中运行代码,如下所示 - 使用limit参数可以轻松管理您希望一次加载的代码数量:
function async(arg, callback) {
console.log('do something with \''+arg+'\', return 1 sec later');
setTimeout(function() { callback(arg * 2); }, 1000);
}
function final() { console.log('Done', results); }
var items = [ 1, 2, 3, 4, 5, 6 ];
var results = [];
var running = 0;
var limit = 2;
function launcher() {
while(running < limit && items.length > 0) {
var item = items.shift();
async(item, function(result) {
results.push(result);
running--;
if(items.length > 0) {
launcher();
} else if(running == 0) {
final();
}
});
running++;
}
}
launcher();