Node.js 如何处理成千上万的请求

人们常说 Node.js 是单线程的。

然而,它却能处理成千上万的请求、读取文件并进行 API 调用,且运行不停歇。

它是如何工作的?

答案是 libuv。

libuv 是一个 C 语言库。它赋予了 Node.js 异步和非阻塞 I/O 的能力。JavaScript 本身无法读取文件或管理网络套接字(sockets)。Node.js 通过 libuv 与操作系统进行通信。

如果没有 libuv,每次读取文件时 JavaScript 都会停止运行。你的应用会变得无响应。

有了 libuv,文件读取会在后台进行,而 JavaScript 可以继续执行其他代码。

示例:

console.log("Start");

fs.readFile("data.txt", "utf8", (err, data) => {
  console.log(data);
});

console.log("End");

输出: Start End (文件内容)

Node.js 在文件读取完成之前就打印了 "End"。它不会原地等待。

libuv 如何管理你的代码:

事件循环 (Event Loop):libuv 运行循环来检查任务是否完成。当任务完成时,它会将回调函数放入队列中。 • 线程池 (Thread Pool):JavaScript 使用单个线程,而 libuv 使用一个工作线程池。默认情况下,该池包含 4 个线程。这些线程负责处理繁重任务,例如:

  • 文件系统操作
  • DNS 查询
  • 压缩
  • 加密 • 网络 (Networking):libuv 管理 HTTP、TCP 和 UDP 套接字。这使得服务器能够同时处理大量连接。 • 定时器 (Timers):libuv 处理 setTimeoutsetInterval

执行流程如下:

  1. JavaScript 运行你的代码。
  2. libuv 将繁重任务移至后台。
  3. JavaScript 继续执行下一行代码。
  4. 任务完成后,libuv 通知事件循环。
  5. 事件循环运行你的回调函数。

想象一家披萨店。

如果没有 libuv,你会站在柜台前,每隔十秒问一次“我的食物好了吗?”。你会阻塞排队的人流。

有了 libuv,你下单后就可以坐下来等待通知。在披萨做好之前,你可以自由地做其他事情。

总结:

• JavaScript 执行:V8 Engine • 事件循环:libuv • 文件 I/O:libuv • 网络:libuv • 定时器:libuv

libuv 是让 Node.js 保持高速运行的引擎。

来源:https://dev.to/kavindotdev/understanding-libuv-the-engine-behind-nodejs-asynchronous-programming-3n7o