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
解决。
据我所知,没有等待调度的事件“队列”。当dispatchEvent
或emit
或类似函数被调用时,该事件的所有侦听器都会在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 可以排队多少个事件?的主要内容,如果未能解决你的问题,请参考以下文章