2

因此,我有一个相当大的文件目录,我需要在 NodeJS 应用程序中使用长时间运行的进程来不断处理这些文件。该目录正在不断处理和清空,但在任何给定时间排队处理 1000 多个文件并不少见 - 它们是压缩的 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(打开的文件太多)错误。请原谅 fs 函数和咖啡脚本的同步版本。

有没有更好的方法以托管方式处理大量文件?最终,我想使用像单个解析流这样的东西——我知道如何使用单个大(甚至不断增长的)文件来做到这一点,但不知道如何使用一个充满单独文件的目录。

这些文件由大量不同的客户端生成到面向公众的 Web 服务器,然后通过安全协议定期将它们同步到我的输入目录。不是一个理想的设置,但考虑到系统的特定性质,这是必要的,它解释了为什么我不能简单地将文件更改为单个多路复用流。

4

2 回答 2

1

不完全是解析流,但可能是朝着它迈出的一步:

您可以使用https://npmjs.org/package/generic-pool来限制正在处理的并发文件的数量。您只需要定义要汇集的资源。

在您的情况下,我假设要池化的资源应该是一个文件处理器,以便一次只能有一个或几个。

您还可以使用某种迭代器方法来简化接下来要处理的文件。

编辑:完成我的回答。我尝试了您的问题并尝试了此 https://gist.github.com/Floby/5064222

于 2013-03-01T10:34:19.560 回答
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();
于 2014-02-19T05:05:44.960 回答