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 处理
setTimeout和setInterval。
执行流程如下:
- JavaScript 运行你的代码。
- libuv 将繁重任务移至后台。
- JavaScript 继续执行下一行代码。
- 任务完成后,libuv 通知事件循环。
- 事件循环运行你的回调函数。
想象一家披萨店。
如果没有 libuv,你会站在柜台前,每隔十秒问一次“我的食物好了吗?”。你会阻塞排队的人流。
有了 libuv,你下单后就可以坐下来等待通知。在披萨做好之前,你可以自由地做其他事情。
总结:
• JavaScript 执行:V8 Engine • 事件循环:libuv • 文件 I/O:libuv • 网络:libuv • 定时器:libuv
libuv 是让 Node.js 保持高速运行的引擎。
