Mik*_*keL 9 stream node.js backpressure
据我所知,Node的事件IO模型的一个后果就是无法告诉Node进程(例如)通过TCP套接字接收数据,阻止,一旦你连接了接收事件处理程序(或者否则开始收听数据).
如果接收器无法足够快地处理传入数据,则可能导致"无限并发",从而节点内的节点继续尽可能快地从套接字读取数据,在事件循环上调度新数据事件而不是阻塞在套接字上,直到进程最终耗尽内存并死掉.
接收方无法告诉节点减慢其读取速度,否则将允许TCP的内置流量控制机制启动并向发送方指示它需要减速.
首先,到目前为止我所描述的是准确的吗?有没有我错过了允许节点避免这种情况的东西?
Node Streams备受推崇的功能之一是自动处理背压.
AFAIK,可写流(tcp套接字)可以告诉它是否需要减速的唯一方法是查看socket.bufferSize(指示写入套接字但尚未发送的数据量).鉴于接收端的节点总是尽可能快地读取,这只能表明发送方和接收方之间的网络连接速度慢,而不是指示接收方是否无法跟上.
那么其次,Node Streams能否以某种方式自动反压在这种情况下处理无法跟上的接收器?
似乎这个问题影响浏览器通过websockets接收数据,原因类似于websockets API没有提供一种机制来告诉浏览器减慢从套接字读取的速度.
Node(以及使用websockets的浏览器)在应用程序级别实现手动流量控制机制,以明确告诉发送进程减速是唯一的解决方案吗?
为了回答您的第一个问题,我相信您的理解是不准确的-至少在流之间传送数据时,这种理解是不正确的。实际上,如果您阅读了pipe()函数的文档,您会发现它明确表示它自动管理流,以使“目标不会被快速可读的流所淹没”。
pipe()的基础实现正在为您处理所有繁重的工作。输入流(可读流)将继续发出数据事件,直到输出流(可写流)已满。顺便说一句,如果我没记错的话,当您尝试写入当前无法处理的数据时,该流将返回false。此时,管道将暂停() Readable流,这将阻止它发出进一步的数据事件。因此,事件循环不会填满并耗尽您的内存,也不会发出只会丢失的事件。而是,Readable将保持暂停状态,直到Writable流发出耗尽事件为止。到那时,管道将resume()可读流。
秘诀在于将一条流输送到另一流中,这将自动为您管理背压。希望这可以回答您的第二个问题,即Node可以并且确实可以通过简单地管道传输流来自动管理此问题。
最后,确实已经不需要手动执行此操作(除非您从头开始编写新的流),因为已经为您提供了它。:)
正如在Node博客中宣布streams2 API 的Node博客文章所承认的那样,处理所有这些都不容易。这是一个很好的资源,当然可以提供比这里更多的信息。但是,出于此处向后兼容的原因,您应该从此处的文档中了解一个并不完全清楚的小陷阱:
如果您附加了数据事件侦听器,则它将把流切换到流模式,并且一旦有数据就会将数据传递给您的处理程序。
因此,请注意,将数据事件侦听器附加到尝试观察流中的某些内容将从根本上将流更改为旧的处理方式。问我我怎么知道。
| 归档时间: |
|
| 查看次数: |
1786 次 |
| 最近记录: |