首先要注意的是:node.js流不限于HTTP请求。HTTP请求/网络资源只是node.js中流的一个示例。
对于所有可以小块处理的事物,流都是有用的。它们使您能够以较小的块处理潜在的巨大资源,从而更轻松地将其装入RAM。
假设您有一个文件(大小为数GB),并且想要将所有小写字母转换为大写字母并将结果写入另一个文件。天真的方法将使用读取整个文件
fs.readFile(为简便起见,省略了错误处理):
fs.readFile('my_huge_file', function (err, data) { var convertedData = data.toString().toUpperCase(); fs.writeFile('my_converted_file', convertedData);});不幸的是,此方法很容易使您的RAM不堪重负,因为在处理文件之前必须先存储整个文件。您还将浪费宝贵的时间等待文件被读取。以较小的块处理文件是否有意义?您可以在等待硬盘提供剩余数据的同时获得第一个字节后立即开始处理:
var readStream = fs.createReadStream('my_huge_file');var writeStream = fs.createWriteStream('my_converted_file');readStream.on('data', function (chunk) { var convertedChunk = chunk.toString().toUpperCase(); writeStream.write(convertedChunk);});readStream.on('end', function () { writeStream.end();});这种方法更好:
- 您将只处理很容易装入RAM的一小部分数据。
- 一旦第一个字节到达,您就开始处理,不要浪费时间做任何事情,而要等待。
打开流后,node.js将打开文件并开始从中读取。一旦操作系统将一些字节传递给正在读取文件的线程,它将被传递给您的应用程序。
回到HTTP流:
- 第一个问题在这里也是有效的。攻击者可能会向您发送大量数据,以淹没您的RAM并关闭(DoS)服务。
- 但是,在这种情况下,第二个问题更为重要:网络可能非常慢(例如智能手机),并且可能需要很长时间才能将所有内容发送给客户端。通过使用流,您可以开始处理请求并缩短响应时间。
暂停HTTP流时:这不是在HTTP级别完成的,但是要低得多。如果您暂停流,node.js将仅停止从底层TCP套接字读取。然后,所发生的事情取决于内核。它仍然可以缓冲传入的数据,因此在您完成当前工作后就可以使用了。它还可以在TCP级别通知发送方它应该暂停发送数据。应用程序不需要处理这些。那不关他们的事。实际上,发件人应用程序甚至可能没有意识到您不再积极阅读!
因此,基本上,这是关于在可用时立即提供数据,但又不会占用您的资源。底层的辛勤工作是由操作系统或者进行(例如
net,
fs,
http),或者通过流的作家,你正在使用(例如,
zlib它是一个
Transform流,并且通常用螺栓固定
fs或
net)。



