当输入流管道传输到多个输出流时,在缓冲区级别上会发生什么?

时间:2019-03-12 03:30:08

标签: javascript node.js stream buffer fs

我正在阅读流文档,并在https://nodejs.org/api/stream.html#stream_buffering上寻找有关流的缓冲行为描述

当通过管道传递到多个输出(因为不同的输出具有不同的消耗速度)时,文档似乎没有提到inputStream缓冲区(或多个缓冲区?)会发生什么情况:

当通过管道传输多个输出时,readystream是否为每个输出保留一个专用缓冲区?

消耗时输出会保持相同的速度还是更快结束?

const input = fs.createReadStream('img.jpg');
const target1 = input.pipe(fs.createWriteStream('target1.jpg'));
const target2 = input.pipe(fs.createWriteStream('target2.jpg'));

1 个答案:

答案 0 :(得分:4)

TL; DR:简短的答案是-较慢的目标流控制流量。

所以首先让我们看看在读取方面会发生什么。

const input = fs.createReadStream('img.jpg');

实例化输入流时,它将在暂停模式下创建并计划读取(没有同步读取,因此它尚无法访问文件)。流中的highWaterMark设置为16384之类的内容,当前缓冲区为0字节。

const target1 = input.pipe(fs.createWriteStream('target1.jpg'));
const target2 = input.pipe(fs.createWriteStream('target2.jpg'));

现在,当您将其实际传输到可写流时,可以通过在pipe method implementation - see the source中添加on('data')事件处理程序来设置流模式。

完成此操作后,我假定不再有程序要运行,因此节点开始实际读取并在上面的处理程序中运行计划的代码,该处理程序将简单地写入所有通过的数据。

当任何目标要写入的数据多于其highWaterMark时,就会发生流控制,这导致了write操作返回false。然后,calling pause here in the code停止读取。在此上方的两行中,您会看到state.awaitDrain递增。

现在,读取的流再次为paused,可写的流将字节写入磁盘-在某些时候,缓冲区级别再次低于highWaterMark。此时,将触发executes this line事件drain,并在所有等待的排水口被调用之后,恢复流程。通过检查递减的awaitDrain属性是否已达到零来完成此操作,这意味着已调用所有等待的消耗事件。

在上述情况下,两个流中较快的流可能在写入时返回虚假值,但肯定会首先消耗虚假值。如果不是awaitDrain,则更快的流将恢复数据流,这将导致两者中较慢的缓冲区溢出。