从节点http服务器下载大文件,服务器内存不足

时间:2014-01-02 02:02:56

标签: node.js

我写了一个简单的http服务器,并下载了一个大文件(1.5G),服务器因内存不足而崩溃

我的代码如下:

var http = require("http");
var fs = require("fs");
var filename = "file.iso";

var serv = http.createServer(function(req,res){
     var stat = fs.statSync(filename);
     res.writeHeader(200,{"Content-Length":stat.size});
     var fReadStream = fs.createReadStream(filename);
     fReadStream.on('data', function (chunk) {
        res.write(chunk);
     });
     fReadStream.on('end', function () {
        res.end();
     });
 });

serv.listen(8888);

但是当我改为使用流的pipe方法时,就好了,就像这样:

var http = require("http");
var fs = require("fs");
var filename = "file.iso";

var serv = http.createServer(function(req,res){
     var stat = fs.statSync(filename);
     res.writeHeader(200,{"Content-Length":stat.size});
     var fReadStream = fs.createReadStream(filename);
     fReadStream.pipe(res);
 });

serv.listen(8888);

我的问题是为什么第一个代码不起作用?

2 个答案:

答案 0 :(得分:4)

我一直在处理Node中的大文件,并注意到加载数据的异步调用可以比http流中的写入调用快得多。这会导致服务器崩溃的瓶颈,因为它会耗尽所有未完成的写入请求(位于缓冲区中)。管道设计用于管理流,以便不会发生这种情况。

From Node documentation:

readable.pipe(destination,[options])#

destination Writable Stream写入数据的目标 options对象管道选项 end Boolean读取器结束时结束写入器。默认= true 此方法从可读流中提取所有数据,并将其写入提供的目标,自动管理流,以便目标不会被快速可读的流淹没。

答案 1 :(得分:3)

我们可以在不使用pipe的情况下平衡读写:

var http = require("http");
var fs = require("fs");
var filename = "file.iso";

var serv = http.createServer(function (req, res) {
    var stat = fs.statSync(filename);
    res.writeHeader(200, {"Content-Length": stat.size});
    var fReadStream = fs.createReadStream(filename);
    fReadStream.on('data', function (chunk) {
       if(!res.write(chunk)){
           fReadStream.pause();
       }
   });
   fReadStream.on('end', function () {
      res.end();
   });
   res.on("drain", function () {
      fReadStream.resume();
   });
});

serv.listen(8888);