Node.js 大型文件的事件循环?

Node.js 大型文件的事件循环?,node.js,webserver,Node.js,Webserver,如果我没有弄错的话,我记得异步I/O(Node.js,Nginx)的“事件循环”模型并不适合为大文件服务 是这样吗?如果是这样的话,有没有解决的办法?我正在考虑在Node中编写一个实时文件浏览器/文件服务器,但文件可能在100MB到3GB之间。我假设事件循环将被阻止,直到文件被完全送达为止?否,它不会被阻止。node.js将以块的形式读取文件,然后将这些块发送给客户端。在块之间,它将为其他请求提供服务 通过网络读取文件和发送数据是I/O绑定的操作。node.js将首先要求操作系统读取文件的一部分

如果我没有弄错的话,我记得异步I/O(Node.js,Nginx)的“事件循环”模型并不适合为大文件服务


是这样吗?如果是这样的话,有没有解决的办法?我正在考虑在Node中编写一个实时文件浏览器/文件服务器,但文件可能在100MB到3GB之间。我假设事件循环将被阻止,直到文件被完全送达为止?

否,它不会被阻止。node.js将以块的形式读取文件,然后将这些块发送给客户端。在块之间,它将为其他请求提供服务

通过网络读取文件和发送数据是I/O绑定的操作。node.js将首先要求操作系统读取文件的一部分,在操作系统执行此操作时,node.js将为另一个请求提供服务。当操作系统带着数据返回node.js时,node.js会告诉操作系统将数据发送到客户端。发送数据时,node.js将为另一个请求提供服务

自己试试看:

创建一个大文件

ddif=/dev/zero of=file.dat bs=1G count=1

运行node.js应用程序

var http = require('http');
var fs = require('fs');

var i = 1;
http.createServer(function (request, response) {
    console.log('starting #' + i++);
    var stream = fs.createReadStream('file.dat', { bufferSize: 64 * 1024 });
    stream.pipe(response);
}).listen(8000);

console.log('Server running at http://127.0.0.1:8000/');
请求<代码>http://127.0.0.1:8000/几次,然后观察node.js如何处理这些问题

如果你要提供大量的大文件,你可能需要尝试不同的值

如果我没有弄错的话,我记得异步的“事件循环”模型 I/O(Node.js、Nginx)不适合服务 大文件

我认为您的观点是正确的,node.js没有针对大文件进行优化。我建议你看看Ryan Dahl的。特别是

幻灯片14

哇。Node在提供大文件方面很差劲。超过3秒的反应 用于在300个并发连接上传输256KB的文件

幻灯片15

发生了什么:V8有一个分代的垃圾收集器。移动 周围的物体是随机的。节点无法获取指向原始字符串数据的指针 写入套接字

幻灯片21

但事实仍然是,将大型字符串推送到套接字的速度很慢

希望这能在未来得到缓解


它们很有趣。也许这已经改变了,但我认为使用NGinx为静态文件(或者CDN)提供服务可能会更好。我认为您误会了NGinx不擅长提供大文件。Node.js在这方面做得不好,因为是V8垃圾回收,而不是事件循环。也可能很有趣。

完美!这非常好,您甚至可以定义缓冲区大小的粒度。与多线程fork方法相比,事件循环在交付所述大文件方面的性能如何?我想,在缓冲区大小方面有一些甜点,这样Node就可以同时处理多个并发流,同时仍然保持响应,但也有意义的进展。幻灯片18显示了NoDE.js在服务缓冲器(和文件可以被读取为缓冲区)时与NGNX一致。@Mak你说得对:)。但我仍然认为node.js可能不是最好的!我想知道当文件变得更大时,这种情况是否会继续下去!甚至Ryan也说“将大字符串推送到套接字的速度很慢”。我对这个问题的好奇更多的是从请求中读取(POST或PUT)大文件,我认为node.js将是一个不错的选择。