如何加速node.js文件操作?

时间:2012-12-29 09:45:41

标签: performance node.js express download mongoose

在我的项目中,客户端将请求从具有id的服务器下载文件。我必须执行以下操作:

  • 验证mongoDb中的ID
  • 检查扩展程序
  • 检查文件是否存在
  • 阅读文件并将内容写入回复

我使用以下代码检查文件并发送响应。

fs.exists(filename, function(exists) {
  if (!exists) {
    res.writeHead(404, '', {
      "Content-Type" : "text/plain"
    })
    res.write("404 Not Found\n");
    res.end();
    return;
  }
  fs.readFile(filename, "binary", function(err, file) {
    if (err) {
      res.writeHead(500, '', {
        "Content-Type" : "text/plain"
      })
      res.write(err + "\n");
      res.end();
      return;
    }
    res.setHeader("Pragma", "public");
    res.setHeader("Cache-Control: private, max-age=3600");
    res.setHeader("Transfer-Encoding:  chunked");
    res.setHeader("Range:  chunked");
    res.writeHead(200, '', {
      "Content-Type" : contentType
    });
    res.write(file, "binary");
    res.end(file, "binary");
  });
});

在几毫秒内,客户端将请求数百个文件。支持的文件类型是图像,音频或视频。

当文件夹中有大量文件时,node.js花费了太多时间来下载文件。如何提高性能?

1 个答案:

答案 0 :(得分:5)

我会推荐一些东西。

  1. 您不应该使用'binary'。根本不要给出编码。通过添加编码,您将使节点执行大量额外工作以将文件的Buffer对象转换为二进制编码的string。当您使用write再次呼叫'binary'时,这意味着节点必须以相反的方式执行相同的操作。此外,您将文件传递给endwrite,这意味着您下载的每个文件都将包含两次文件数据。

  2. 我建议不要使用readFile。由于readFile在您的file变量中将整个文件内容传递给您,您需要节点将文件的全部内容加载到RAM中,这意味着它需要分配大量缓冲区然后连接他们,这是不必要的工作。

  3. 没有理由单独使用exists,因为如果您尝试打开不存在的文件,错误会告诉您,因此首先检查只是额外的工作。

  4. 此外,Transfer-encoding标题将自行设置,您无需执行此操作。

    这样的事情应该更快:

    fs.createReadStream(filename)
        .on('error', function(err){
            if (err.code === 'ENOENT'){
                res.writeHead(404, {
                    'Content-type': 'text/plain'
                });
                res.end('404 Not Found\n');
            } else {
                res.writeHead(500, {
                    'Content-type': 'text/plain'
                });
                res.end(err + '\n');
            }
        })
        .on('open', function(){
            res.writeHead(200, {
                'Pragma': 'public',
                'Cache-Control': 'private, max-age=3600',
                'Content-type': contentType
            });
        })
        .pipe(res);