简体   繁体   English

NodeJs流管道是否对称?

[英]Does NodeJs stream pipe is symmetric?

I'm building a server which transfers files from endpoint A to endpoint B. 我正在构建一个服务器,该服务器将文件从端点A传输到端点B。

I'm wondering if the NodeJs stream pipe is symmetric? 我想知道NodeJs流管道是否对称? If I do the following: request.get(A).pipe(request.put(B)); 如果我执行以下操作: request.get(A).pipe(request.put(B)); , does it upload as fast as it downloads? ,上传速度和下载速度一样快吗?

I'm asking this question, because my server has an asymmetric connexion (it downloads faster than upload), and I try to avoid memory consumption. 我问这个问题,因为我的服务器具有非对称连接(下载速度比上传速度快),并且我尝试避免占用内存。

According to node's documentation on stream#pipe pipe will switch the read stream to flowing mode - it will read only when the write stream has finished consuming previous packets. 根据节点在stream#pipe上文档,管道将读取流切换为流模式-仅在写入流完成使用以前的数据包时才读取。

readable.pipe() method attaches a Writable stream to the readable, causing it to switch automatically into flowing mode and push all of its data to the attached Writable. visible.pipe()方法将Writable流附加到可读,从而使其自动切换到流模式,并将其所有数据推送到附加的Writable。 The flow of data will be automatically managed so that the destination Writable stream is not overwhelmed by a faster Readable stream. 数据流将被自动管理,以使目标可写流不会被更快的可读流淹没。

So your transfer may be asymmetrical, due to different send/download speed - the difference may be buffered in Node's memory - Buffering of streams 因此,由于不同的发送/下载速度,您的传输可能是不对称的-差异可能会缓冲在Node的内存中- 流的缓冲

Buffering# 缓冲#

Both Writable and Readable streams will store data in an internal buffer that can be retrieved using writable._writableState.getBuffer() or readable._readableState.buffer, respectively. 可写流和可读取流都将数据存储在内部缓冲区中,可以分别使用writable._writableState.getBuffer()或可读._visibleState.buffer检索数据。

The amount of data potentially buffered depends on the highWaterMark option passed into the streams constructor. 可能缓冲的数据量取决于传递到流构造函数中的highWaterMark选项。 For normal streams, the highWaterMark option specifies a total number of bytes . 对于普通流,highWaterMark选项指定字节总数 For streams operating in object mode, the highWaterMark specifies a total number of objects. 对于以对象模式运行的流,highWaterMark指定对象的总数。

Data is buffered in Readable streams when the implementation calls stream.push(chunk). 当实现调用stream.push(chunk)时,数据将缓存在Readable流中。 If the consumer of the Stream does not call stream.read(), the data will sit in the internal queue until it is consumed. 如果Stream的使用者未调用stream.read(),则数据将位于内部队列中,直到被使用为止。

Once the total size of the internal read buffer reaches the threshold specified by highWaterMark, the stream will temporarily stop reading data from the underlying resource until the data currently buffered can be consumed (that is, the stream will stop calling the internal readable._read() method that is used to fill the read buffer). 一旦内部读取缓冲区的总大小达到highWaterMark指定的阈值,流将暂时停止从底层资源读取数据,直到可以使用当前缓冲的数据为止 (也就是说,流将停止调用内部read._read() )用于填充读取缓冲区的方法)。

Data is buffered in Writable streams when the writable.write(chunk) method is called repeatedly. 当重复调用writable.write(chunk)方法时,数据将缓存在可写流中。 While the total size of the internal write buffer is below the threshold set by highWaterMark, calls to writable.write() will return true. 当内部写缓冲区的总大小低于highWaterMark设置的阈值时,对writable.write()的调用将返回true。 Once the the size of the internal buffer reaches or exceeds the highWaterMark, false will be returned. 一旦内部缓冲区的大小达到或超过highWaterMark,将返回false。

A key goal of the stream API, and in particular the stream.pipe() method, is to limit the buffering of data to acceptable levels such that sources and destinations of differing speeds will not overwhelm the available memory . 流API(尤其是stream.pipe()方法)的关键目标是将数据缓冲限制在可接受的水平,以使速度不同的源和目标不会占用可用内存

Because Duplex and Transform streams are both Readable and Writable, each maintain two separate internal buffers used for reading and writing, allowing each side to operate independently of the other while maintaining an appropriate and efficient flow of data. 由于双工流和变换流都是可读和可写的,因此每个流维护两个用于读取和写入的独立内部缓冲区,从而允许每一侧独立于另一端运行,同时保持适当且有效的数据流。 For example, net.Socket instances are Duplex streams whose Readable side allows consumption of data received from the socket and whose Writable side allows writing data to the socket. 例如,net.Socket实例是双工流,其“可读”侧允许使用从套接字接收的数据,而其“可写”侧允许将数据写入到套接字。 Because data may be written to the socket at a faster or slower rate than data is received, it is important each side operate (and buffer) independently of the other. 由于可能以比接收数据快或慢的速率将数据写入套接字,因此,每一面都必须彼此独立地操作(和缓冲),这一点很重要。

I recommend that you look at this question here the topic is elaborated a further. 我建议您在这里进一步讨论这个问题

If you run the following sample 如果运行以下示例

const http = require('http');

http.request({method:'GET', host:'somehost.com', path: '/cat-picture.jpg'}, (response)=>{
  console.log(response);
}).end()

you can explore the underlying sockets - on my system they all have the highWaterMark : 16384 property. 您可以浏览基础套接字-在我的系统上,它们都具有highWaterMark : 16384属性。 So if I understand the documentation, and the above-mentioned questions, in your case about 16KB may be buffered in the faster GET socket on Node.js level - what happens below is probably highly dependent on your system/network configuration. 因此,如果我理解文档以及上面提到的问题,则在您的情况下,大约16KB的内存可能会存储在Node.js级别上更快的GET套接字中-下面发生的情况可能高度取决于您的系统/网络配置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM