Nodejs 的内部线程池究竟是如何工作的?

How Nodejs's internal threadpool works exactly?

我已经阅读了很多关于 NodeJs 工作原理的文章。但是我还是搞不懂Nodejs内部线程到底是怎么进行IO操作的。

在这个回答中,他说NodeJs的线程池中有4个内部线程来处理I/O操作。那么如果我同时有 1000 个请求,每个请求都想做 I/O 操作,比如从数据库中检索大量数据。 NodeJs 会将这些请求分别传递给这 4 个工作线程,而不会阻塞主线程。所以NodeJs最多可以同时处理的I/O个操作是4个操作。我错了吗?

如果我是对的,剩下的请求将在哪里处理?。主单线程是非阻塞的,一直把请求驱动到对应的operators,那么当所有的worker线程都满任务的时候,这些请求会去哪里呢? .

在下图中,所有内部工作线程都充满了任务,假设它们都需要从数据库中检索大量数据和主单线程不断向这些工人提出新的请求,这些请求将去哪里?它是否有一个内部任务队列来存储这些请求?

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

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

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

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

libuv 提供的单个、每进程线程池默认创建 4 个线程。 UV_THREADPOOL_SIZE 环境变量可用于更改 node 进程启动时创建的线程数,最大值为 1024(从 libuv 版本 1.30.0 开始)。

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

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

非阻塞IO,大部分网络操作都支持,不需要使用线程池

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

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

In the image below , all of the internal worker threads are full of task , assume all of them need to retrieve a lot of data from the database and the main single thread keep driving new requests to these workers

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

根据Node.js documentation,线程是这样使用的:

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

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

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

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