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

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

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

【问题讨论】:

  • 我不认为有限制,但你的内存。
  • 我相信事件实际上总是排队的。
  • 我不认为事件队列是这样处理的

标签: javascript node.js message-queue event-loop


【解决方案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(这可能表明您的任务队列非常大)。

【讨论】:

  • 哇,真是一个了不起的答案。非常感谢
猜你喜欢
  • 2014-03-07
  • 1970-01-01
  • 2011-08-23
  • 2019-04-18
  • 2012-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-10
相关资源
最近更新 更多