Node.js 可以排队多少个事件?
How many events can Node.js queue?
据我所知,如果 Node 中的事件需要 "long time" 进行调度,Node 会创建某种 "queue of events",并且它们会尽快被触发,一个接一个。
这个队列能排多久?
同步调用特定事件的处理程序(按添加顺序)一旦事件发出,它们就不会延迟。
事件处理程序的总数仅受限于 v8 and/or可用 RAM 的数量。
我相信您在谈论可能需要未定义时间才能完成的操作,例如 http 请求或文件系统访问。
Node 为您提供了一种异步完成这些类型操作的方法,这意味着您可以告诉 Node 或第 3 方库开始操作,然后调用一些代码(您定义的函数)来通知您在操作完成时。这可以通过事件侦听器或回调函数来完成,它们都有自己的局限性。
对于事件侦听器,您可以拥有的最大侦听器数量取决于您环境的最大数组大小。在 node.js 的情况下,javascript 引擎是 v8,但根据 this post 第 5 版 ECMA 标准规定的最大值约为 40 亿个元素,这是您应该永远克服不了。
对于回调,您的限制是最大调用堆栈大小,这意味着您的函数可以相互调用多深。例如,您可以有一个回调调用一个回调调用一个回调调用另一个回调,等等。调用堆栈大小决定了回调调用回调的可能性。请注意,调用堆栈大小可能是事件侦听器的限制,而且它们本质上是可以多次执行的回调。
这些是每个的限制。
虽然这似乎是一个简单的问题,但实际上是一个相当复杂的问题;不幸的是,没有任何人可以给你的简单数字。
首先:墙上的时间在这里并没有真正发挥作用。所有事件都以相同的方式调度,无论事情是否正在 "a long time." 换句话说,所有事件都通过 "queue."
其二:没有单队列。有很多地方可以将不同类型的事件分派到 JS 中。 (以下假设你know what a tick is。)
- 您(或您使用的库)传递给
process.nextTick()
的东西。它们在当前滴答结束时被调用,直到 nextTick 队列为空。
- 您(或您使用的库)传递给
setImmediate()
的东西。它们在下一个滴答开始时被调用。 (这意味着 nextTick
任务可以无限期地将事物添加到当前滴答中,从而防止其他操作发生,而 setImmediate
任务只能将事物添加到下一个滴答的队列中。)
- I/O 事件分别由 libuv 通过
epoll
/kqueue
/IOCP 在 Linux/Mac/Windows 上处理。当 OS 通知 libuv I/O 已经发生时,它会依次调用 JS 中的适当处理程序。事件循环的给定滴答可能会处理零个或多个 I/O 个事件;如果一个 tick 需要很长时间,I/O 事件将在 操作系统 队列中排队。
- Signals 由 OS.
发送
- 在单独的线程上执行的本机代码 (C/C++) 可能会调用 JS 函数。这通常通过 libuv work queue.
来完成
由于有很多工作可能需要排队的地方,it is not easy to answer "how many items are currently queued",更不用说这些队列的绝对限制是多少了。本质上,任务队列大小的硬性限制是可用 RAM。
实际上,您的应用将:
- 达到 V8 堆约束
- 对于I/O,最大允许打开文件描述符的数量。
...在任何队列的大小成为问题之前。
如果您只对您的应用程序是否处于高负载下感兴趣,toobusy 可能会引起您的兴趣——它对事件循环的每个滴答进行计时,以确定您的应用程序是否花费了处理每个滴答的时间异常长(这可能表明您的任务队列非常大)。
据我所知,如果 Node 中的事件需要 "long time" 进行调度,Node 会创建某种 "queue of events",并且它们会尽快被触发,一个接一个。
这个队列能排多久?
同步调用特定事件的处理程序(按添加顺序)一旦事件发出,它们就不会延迟。
事件处理程序的总数仅受限于 v8 and/or可用 RAM 的数量。
我相信您在谈论可能需要未定义时间才能完成的操作,例如 http 请求或文件系统访问。
Node 为您提供了一种异步完成这些类型操作的方法,这意味着您可以告诉 Node 或第 3 方库开始操作,然后调用一些代码(您定义的函数)来通知您在操作完成时。这可以通过事件侦听器或回调函数来完成,它们都有自己的局限性。
对于事件侦听器,您可以拥有的最大侦听器数量取决于您环境的最大数组大小。在 node.js 的情况下,javascript 引擎是 v8,但根据 this post 第 5 版 ECMA 标准规定的最大值约为 40 亿个元素,这是您应该永远克服不了。
对于回调,您的限制是最大调用堆栈大小,这意味着您的函数可以相互调用多深。例如,您可以有一个回调调用一个回调调用一个回调调用另一个回调,等等。调用堆栈大小决定了回调调用回调的可能性。请注意,调用堆栈大小可能是事件侦听器的限制,而且它们本质上是可以多次执行的回调。
这些是每个的限制。
虽然这似乎是一个简单的问题,但实际上是一个相当复杂的问题;不幸的是,没有任何人可以给你的简单数字。
首先:墙上的时间在这里并没有真正发挥作用。所有事件都以相同的方式调度,无论事情是否正在 "a long time." 换句话说,所有事件都通过 "queue."
其二:没有单队列。有很多地方可以将不同类型的事件分派到 JS 中。 (以下假设你know what a tick is。)
- 您(或您使用的库)传递给
process.nextTick()
的东西。它们在当前滴答结束时被调用,直到 nextTick 队列为空。 - 您(或您使用的库)传递给
setImmediate()
的东西。它们在下一个滴答开始时被调用。 (这意味着nextTick
任务可以无限期地将事物添加到当前滴答中,从而防止其他操作发生,而setImmediate
任务只能将事物添加到下一个滴答的队列中。) - I/O 事件分别由 libuv 通过
epoll
/kqueue
/IOCP 在 Linux/Mac/Windows 上处理。当 OS 通知 libuv I/O 已经发生时,它会依次调用 JS 中的适当处理程序。事件循环的给定滴答可能会处理零个或多个 I/O 个事件;如果一个 tick 需要很长时间,I/O 事件将在 操作系统 队列中排队。 - Signals 由 OS. 发送
- 在单独的线程上执行的本机代码 (C/C++) 可能会调用 JS 函数。这通常通过 libuv work queue. 来完成
由于有很多工作可能需要排队的地方,it is not easy to answer "how many items are currently queued",更不用说这些队列的绝对限制是多少了。本质上,任务队列大小的硬性限制是可用 RAM。
实际上,您的应用将:
- 达到 V8 堆约束
- 对于I/O,最大允许打开文件描述符的数量。
...在任何队列的大小成为问题之前。
如果您只对您的应用程序是否处于高负载下感兴趣,toobusy 可能会引起您的兴趣——它对事件循环的每个滴答进行计时,以确定您的应用程序是否花费了处理每个滴答的时间异常长(这可能表明您的任务队列非常大)。