Node.js 可以排队多少个事件?

Posted

技术标签:

【中文标题】Node.js 可以排队多少个事件?【英文标题】:How many events can Node.js queue? 【发布时间】:2016-03-12 10:35:23 【问题描述】:

据我所知,如果 Node 中的一个事件需要“很长时间”才能被调度,Node 会创建某种“事件队列”,并且它们会尽快被一一触发。

这个队列可以排多长时间?

【问题讨论】:

我不认为有限制,但你的内存。 我相信事件实际上总是排队的。 我不认为事件队列是这样处理的 【参考方案1】:

特定事件的处理程序被同步调用(按添加顺序)一旦事件发出,它们根本不会延迟。

事件处理程序的总数仅受 v8 和/或可用 RAM 量的限制。

【讨论】:

如果达到 ram 限制,节点是否会暂停调度其他事件,直到释放更多内存或 VM 会直接终止?我试图了解这是否是我的OOM problem @DmitryB。如果 v8 无法分配更多内存并尝试 GC 足够的空间失败,它就会死掉,就像大多数其他程序一样。【参考方案2】:

我相信您所说的操作可能需要不确定的时间才能完成,例如 http 请求或文件系统访问。

Node 为您提供了一种异步完成这些类型操作的方法,这意味着您可以告诉 node 或 3rd 方库开始操作,然后调用一些代码(您定义的函数)来通知您何时操作完成。这可以通过事件侦听器或回调函数来完成,它们都有自己的局限性。

对于事件侦听器,您可以拥有的最大侦听器数量取决于您的环境的最大数组大小。在 node.js 的情况下,javascript 引擎是 v8,但根据this post,第 5 版 ECMA 标准规定了大约 40 亿个元素的最大值,这是您永远不应该克服的限制。

对于回调,您的限制是最大调用堆栈大小,这意味着您的函数可以相互调用多深。例如,您可以让一个回调调用一个回调调用一个回调调用另一个回调,等等。调用堆栈大小决定了回调调用回调的可能性。请注意,调用堆栈大小可能是事件侦听器的限制,它们本质上是可以多次执行的回调。

这些都是各自的限制。

【讨论】:

重新事件监听器,数组大小是对监听事件的回调函数个数的限制,而不是对要调度的事件队列大小的限制.此外,调用堆栈限制可以通过setImmediate/process.nextTick 解决。 据我所知,没有等待调度的事件“队列”。当dispatchEventemit 或类似函数被调用时,该事件的所有侦听器都会在dispatchEvent 返回之前被调用。当然,您可以有嵌套的事件分派,其中事件侦听器可以分派另一个事件,但仍然没有“排队”。虽然这是我对事件的经验。节点可能使用某种机制来重置使用队列的调用堆栈?但我如何描述它通常是事件的工作方式。 另外,是的,数组大小限制是对一种事件类型可以拥有的侦听器数量的限制。 您所描述的是EventEmitter(JavaScript 模块)的工作方式,并且通常适用于用户代码 (JS) 如何发出事件。但是,在原生方面,有几种不同类型的队列我describe。 我想这就是我们所说的,因为它有一个 javascript 标签。您的回答对我来说很有趣,因为我没有深入研究节点的本机方面。【参考方案3】:

虽然这似乎是一个简单的问题,但它实际上是一个相当复杂的问题;不幸的是,没有任何人可以给你一个简单的数字。

首先:墙上的时间在这里并没有真正发挥作用。所有事件都以相同的方式分派,无论事情是否需要“很长时间”。换句话说,所有事件都经过一个“队列”。

第二:没有单一的队列。有很多地方可以将不同类型的事件分派到 JS 中。 (以下假设您know what a tick is。)

您(或您使用的库)传递给process.nextTick() 的东西。它们在当前滴答结束时被调用,直到 nextTick 队列为空。 您(或您使用的库)传递给setImmediate() 的东西。它们在下一个刻度开始时被调用。 (这意味着nextTick 任务可以无限期地向当前滴答添加内容,防止其他操作发生,而setImmediate 任务只能将内容添加到下一个滴答的队列中。) I/O 事件由libuv 通过epoll/kqueue/IOCP 在Linux/Mac/Windows 上分别处理。当操作系统通知 libuv 发生了 I/O 时,它会依次调用 JS 中的相应处理程序。事件循环的一个给定滴答可能会处理零个或多个 I/O 事件;如果一个滴答需要很长时间,I/O 事件将在操作系统队列中排队。 操作系统发送的Signals。 在单独线程上执行的本机代码 (C/C++) 可能会调用 JS 函数。这通常通过libuv work queue 完成。

由于有很多地方可以排队工作,it is not easy to answer "how many items are currently queued",更不用说这些队列的绝对限制了。本质上,任务队列大小的硬性限制是可用 RAM。

实际上,您的应用将:

命中 V8 堆约束 对于 I/O,将允许打开的文件描述符的数量设为最大值。

...在任何队列的大小成为问题之前。

如果您只是对您的应用是否处于高负载感兴趣,toobusy 可能会感兴趣 - 它会计算事件循环的每个滴答声,以确定您的应用是否花费了异常多的时间处理每个tick(这可能表明您的任务队列非常大)。

【讨论】:

哇,真是一个了不起的答案。非常感谢

以上是关于Node.js 可以排队多少个事件?的主要内容,如果未能解决你的问题,请参考以下文章

一个数组可以处理多少个项目 node.js

理解 node.js 的事件循环

Node.js进击基础一(5-11事件模块)

node.js事件循环 event loop

Node.js 事件循环

Node.js学习