首页 > 解决方案 > Node.js 是否委托多线程?

问题描述

我有一个带有执行 fs.readFile 操作的 REST 端点的快速服务器的示例代码。我知道该操作是异步的,不会阻塞作为单线程进程运行的主线程。但是我想澄清一下当有数百个对 Node.js 服务器的请求并且请求在 I/O 中排队时会发生什么。在 I/O 的后台发生的文件读取操作是否有任何类型的多线程等级?或者这也只是一个单线程操作?如果是这样,它不会成为大量请求的瓶颈吗?

标签: node.jsexpressfs

解决方案


node.js 中的文件 I/O 使用线程池(用于与文件操作关联的本机代码)。有一个用于挂起文件 I/O 操作的队列,线程池中的每个线程从队列中获取一个事件,处理它,完成它,触发完成事件,然后从队列中获取下一个挂起的文件 I/O 操作,然后处理它。

从 Javascript 方面来看,这都是非阻塞的。当您调用其中一个异步文件操作时,它会被移交给文件 I/O 子系统,并立即将控制权返回给 JS 引擎以运行其他 JS。稍后,当内部系统完成文件 I/O 操作,并将事件添加到 node.js 事件队列中,并且当时正在运行的任何 JS 完成并到达 node.js 事件队列中的下一个事件时,然后调用与完成该异步文件操作相关的回调,并运行与其相关的 JS。

我有一个带有执行 fs.readFile 操作的 REST 端点的快速服务器的示例代码。我知道该操作是异步的,不会阻塞作为单线程进程运行的主线程。

那是对的。

但是我想澄清一下当有数百个对 Node.js 服务器的请求并且请求在 I/O 中排队时会发生什么。在 I/O 的后台发生的文件读取操作是否有任何类型的多线程等级?

数百个请求将堆积在内部文件 I/O 队列中,并且它们将由用于文件 I/O 的内部本机代码的线程池中的 N 个线程一次提供 N 个服务。

或者这也只是一个单线程操作?如果是这样,它不会成为大量请求的瓶颈吗?

一次是 N 个线程(线程池中的线程数)。是的,这将是一个瓶颈。无论如何编程,同时执行数百个文件请求总是会成为某种瓶颈,因为在最低级别,磁盘一次只能查找一个位置并一次读取磁盘的一部分. node.js 内部的线程池大小是可控的,但是如果你所有的磁盘 I/O 请求都到同一个底层磁盘,你会达到一个地步,通过添加更多的线程来提高效率。争夺磁盘上相同的读/写磁头。

如果您想了解更多关于 node.js 事件循环和其他子系统如何工作的信息,这里有很多关于该主题的有用文章:

Node.Js 单线程机制如何工作?了解 NodeJs 中的事件循环

处理 IO — NodeJS 事件循环第 4 部分

node.js 事件循环如何工作

Node.js 事件循环、计时器和 process.nextTick()

关于线程池的 libuv 文档并对其进行自定义


推荐阅读