最有效地下载,解压缩和分析Node JS中的许多文件

时间:2018-03-10 00:09:02

标签: node.js performance download zip

我必须从第三方主机将大量压缩文件下载到我的Node JS服务器上,解压缩,分析并存储它们。这些文件略多于18000个XML,每个XML介于约0.01和0.06mb之间。这些文件被分成8个大小不一的压缩文件夹。

现在,这是我的过程:

  1. 使用request

    下载压缩文件

    request({ url: fileUrl, encoding: null }, function(err, resp, body) {...});

  2. 将下载的文件写入目录

    fs.writeFile(output, body, function(err) {...});

  3. 使用extract-zip解压缩下载的资料并放入新目录

    unzip(output, { dir : directory }, function (err) {...});

  4. 删除下载的zip文件

    fs.unlink('/a-directory/' + output, (err) => { if (err) console.log(err); });

  5. 获取目录中的项目

    fs.readdir(fromDir, function(err, items) {...});

  6. 对于每个项目(XML文件),请阅读

    fs.readFile(fromDir + '/' + item, 'utf8', function(err, xmlContents) {...});

  7. 对于每个读取的XML文件,将其转换为JSON

    let bill = xmlToJsonParser.toJson(xmlContents)

  8. 会做其他一些事情,但我还没写过那部分

  9. 如果能帮助任何人,我可以发布更完整的代码。

    正如你所看到的,这里有很多步骤,我预感到其中一些可以删除或至少提高效率。

    你对提高性能有什么建议? - 现在这个过程完成了,但我每次都达到了100%的CPU,我相当肯定是坏的。

1 个答案:

答案 0 :(得分:1)

扩展此类工作的一些一般准则:

  1. 完全异步I / O的步骤在node.js中非常好。
  2. 在进行大量I / O操作时,您将希望能够同时控制有多少I / O操作来控制内存使用和TCP资源使用。因此,您可能一次启动数百个请求,而不是一次启动18,000个请求。完成后,启动下一个。
  3. 使用有意义量CPU的步骤应该在一个可以运行其中N个的过程中(通常与CPU一样多)。这有助于您的CPU使用率扩展。
  4. 尽量避免在内存中保留比您需要的更多内容。如果你可以直接从网络管道到磁盘,这可以显着减少内存使用量,缓冲整个文件,然后将整个文件写入磁盘。
  5. 找出管理等待工作进程运行的作业的工作队列的一些方法。您可以让主应用程序维护队列并使用http来请求下一个作业,或者您甚至可以通过带有锁定文件的文件系统来处理它。
  6. 所以,这里有一些基于这些指南的更具体的细节:

    我说使用主服务器进程执行步骤1和2.前两个步骤都不是CPU密集型的,因此单个服务器进程应该能够处理其中的大量数据。他们所做的只是异步I / O.您必须同时管理有多少request()次操作,以避免TCP堆栈或内存使用量过载,但除此之外,这应该可以扩展,因为它只进行异步I / O。

    您可以通过将响应直接传送到输出文件来减少步骤1和2中的内存使用量,以便在字节到达时立即将它们写入磁盘,而不将整个文件保存在内存中。

    然后编写另一个执行步骤3 - 8的node.js应用程序(步骤3和7可能是CPU密集型)。如果你以一种只是"结帐"来自已知目录的文件并对其进行处理,您应该能够创建它,以便您可以像运行CPU一样运行这些进程,从而获得扩展,同时还可以使CPU负载远离主进程。

    结账功能可以通过一个中央存储(如redis商店,甚至只是一个维护工作队列的简单服务器)来跟踪哪些文件可用于工作,或者你甚至可以使用锁定文件完全使用文件系统逻辑实现它。

      

    现在该过程完成,但我每次都达到100%的CPU,我相当肯定是坏的。

    如果您只有一个进程并且它处于100%CPU,那么您可以通过获取更多进程来增加规模。

      

    正如你所看到的,这里有很多步骤,我预感到其中一些可以删除或至少提高效率。

    一些想法:

    1. 如前所述,将您的请求直接传递给下一个操作,而不是缓冲整个文件。
    2. 如果您拥有正确的解压缩工具,您甚至可以将请求直接传递给直接通过管道传输到文件的解压缩程序。如果你这样做,你必须水平扩展主进程以获得更多的CPU,但这样可以节省读取和写入压缩文件到磁盘或从磁盘写入。您可以想象将步骤1-4组合成一个使用解压缩变换的流写入。
    3. 如果您执行了步骤2中描述的转换流,那么您将拥有一组执行步骤5-8的单独进程。
    4. 以下是一些可用于组合管道和解压缩的库:

      unzip-stream

      node-unzip-2