Nodejs的内部线程池如何正常工作?

时间:2015-04-02 04:03:36

标签: javascript node.js multithreading event-loop

我已经阅读了很多关于NodeJ如何工作的文章。但我仍然无法弄清楚Nodej的内部线程是如何进行IO操作的。

在这个答案https://stackoverflow.com/a/20346545/1813428中,他说NodeJ的线程池中有4个内部线程来处理I / O操作。那么,如果我同时有1000个请求,每个请求都想进行I / O操作,例如从数据库中检索大量数据。 NodeJs将分别​​将这些请求传递给这4个工作线程,而不会阻塞主线程。因此,NodeJ可以同时处理的最大I / O操作数是4个操作。我错了吗?。

如果我是对的,剩下的请求将在哪里处理?主要的单线程是非阻塞的并且继续将请求驱动到相应的操作员,那么这些请求在所有工作线程充满任务的情况下会在哪里进行? 。

在下图中,所有内部工作线程都充满了任务,假设他们都需要从数据库中检索大量数据并且主要单线程继续驱动新请求这些工人,这些要求会在哪里?是否有内部任务queuse来存储这些请求?

enter image description here

3 个答案:

答案 0 :(得分:11)

libuv提供的单个每进程线程池默认创建4个线程。 UV_THREADPOOL_SIZE环境变量可用于更改node进程启动时创建的线程数,最大值为128。

当所有这些线程被阻止时,进一步使用它们的请求将排队。请求线程的API方法称为uv_queue_work

此线程池用于将导致阻止 IO的任何系统调用,其中包括本地文件系统操作。它也可以用来减少CPU密集型操作的影响,正如@Andrey提到的那样。

大多数网络操作都支持

非阻塞 IO,不需要使用线程池。

如果您正在使用的数据库驱动程序的源代码可用,并且您能够找到对uv_queue_work的引用,那么它可能正在使用该线程池。

如果需要,libuv thread pool文档提供了更多技术细节。

答案 1 :(得分:1)

不,线程池的主要用例是卸载CPU密集型操作。 IO在一个线程中执行 - 如果您并行等待外部数据,则不需要多个线程,而事件循环恰好是组织执行流程的技术,以便您尽可能并行地等待

实施例: 您需要发送100封带有问题(y / n)的电子邮件和另外一封带有已回答" y"的电子邮件。写电子邮件大约需要30秒,平均需要2小时才能回复+ 10秒阅读回复。你开始写所有100封电子邮件(50分钟的时间),然后你等待警报声,每次回复到来时唤醒你,当你收到答案时,你会增加" y"的数量。你需要在2小时50分钟内完成。这是异步IO和事件循环(无线程池)的示例

阻止示例:发送电子邮件,等待回答,重复。需要4天(如果你可以克隆另一个你需要两天)

异步线程池示例:每个响应都是您不知道的语言。你有4个翻译朋友。您通过电子邮件将文本发送给他们,然后他们通过电子邮件将翻译后的文本发送给您(或者,更准确:您打印文本并将其放入"需要翻译"文件夹。每当翻译器可用时,文本都从文件夹中提取)

答案 2 :(得分:0)

<块引用>

在下图中,所有的内部工作线程都充满了任务,假设它们都需要从数据库中检索大量数据,并且主单线程不断向这些工作线程发送新请求

这不是 node.js 使用这些线程的方式。

根据Node.js documentation,线程的使用方式如下:

enter image description here

所有请求和响应都在主线程中“处理”。 您的回调(以及 await 之后的代码)只是轮流执行。 javascript解释器和“事件循环”之间的“循环”通常只是一个while循环。

除了您自己启动的 worker_threads 之外,node.js 使用线程的目的只有 4 件事:等待 DNS 响应、磁盘 I/O、内置 crypto 库和内置 {{3 }} 图书馆。 Worker_threads 是 node.js 在主线程之外执行 javascript 的唯一地方。线程的所有其他用途都执行 C/C++ 代码。

如果你想了解更多,我已经写了几个相关问题的答案:

zip

Node js architecture and performance

how node.js server is better than thread based server

node js - what happens to incoming events during callback excution

Does javascript process using an elastic racetrack algorithm