gpt4 book ai didi

基于 TCP 的 Node.JS 无界并发/流背压

转载 作者:IT老高 更新时间:2023-10-28 23:26:41 26 4
gpt4 key购买 nike

据我了解,Node 事件 IO 模型的后果之一是,一旦您连接了接收事件,就无法告诉(例如)通过 TCP 套接字接收数据的 Node 进程阻塞处理程序(或以其他方式开始监听数据)。

如果接收方不能足够快地处理传入的数据,则可能会导致“无限并发”,即引擎盖下的 Node 会继续尽可能快地从套接字读取数据,并在事件上安排新的数据事件在套接字上循环而不是阻塞,直到进程最终耗尽内存并死亡。

接收方不能告诉 Node 放慢读取速度,否则会允许 TCP 的内置流量控制机制启动并向发送方指示它需要放慢速度。

首先,到目前为止我所描述的是否准确?有什么我错过的东西可以让 Node 避免这种情况吗?

Node Streams 备受吹捧的功能之一是自动处理背压。

AFAIK,可写流(tcp 套接字)判断它是否需要减速的唯一方法是查看 socket.bufferSize(指示写入套接字但尚未发送)。鉴于接收端的 Node 总是尽可能快地读取,这只能表明发送方和接收方之间的网络连接速度较慢,而不是接收方是否跟不上。

其次,Node Streams 自动背压能否在这种情况下以某种方式工作以处理无法跟上的接收器?

这个问题似乎也影响了通过 websockets 接收数据的浏览器,原因类似,websockets API 没有提供一种机制来告诉浏览器减慢它从套接字的读取速度。

对于 Node(以及使用 websockets 的浏览器)来说,解决这个问题的唯一方法是在应用程序级别实现手动流量控制机制,以明确告诉发送进程放慢速度吗?

最佳答案

为了回答您的第一个问题,我认为您的理解并不准确——至少在流之间传输数据时不准确。事实上,如果您阅读了 pipe() function 的文档,您会看到它明确表示它会自动管理流,因此“目标不会被快速可读的流淹没。”

pipe() 的底层实现为您处理所有繁重的工作。输入流(Readable 流)将继续发出 data事件,直到输出流(Writable 流)已满。顺便说一句,如果我没记错的话,当您尝试写入当前无法处理的数据时,流将返回 false。此时,管道将pause()可读流,这将阻止它发出进一步的数据事件。因此,事件循环不会填满和耗尽您的内存,也不会发出简单丢失的事件。相反,Readable 将保持暂停,直到 Writable 流发出 drain事件。此时,管道将resume()可读流。

秘诀在于将一条流引入另一条流,它会自动为您管理背压。这有望回答您的第二个问题,即 Node 可以并且确实通过简单的管道流自动管理此问题。

最后,实际上没有必要手动实现它(除非您从头开始编写新的流),因为它已经为您提供了。 :)

处理这一切并不容易,正如宣布 streams2 的 Node 博客文章所承认的那样。 Node 中的 API。这是一个很好的资源,当然比我在这里提供的信息要多得多。然而,您应该知道的一个不完全明显的小问题,来自文档 here并且出于向后兼容性的原因:

If you attach a data event listener, then it will switch the stream into flowing mode, and data will be passed to your handler as soon as it is available.

因此请注意,附加数据事件监听器以尝试观察流中的某些内容将从根本上将流更改为旧的做事方式。问我how I know .

关于基于 TCP 的 Node.JS 无界并发/流背压,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25237013/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com