Node.js 非阻塞行为的新手查询
Posted
技术标签:
【中文标题】Node.js 非阻塞行为的新手查询【英文标题】:Newbie query on Node.js non-blocking behavior 【发布时间】:2012-05-11 04:22:36 【问题描述】:一直在关注这个神话般的tutorial。作为 javascript 和函数式编程的新手,我想了解非阻塞的本质含义。我故意在我的 JS 代码中添加了 10 秒的“睡眠”,以实现阻塞行为。
function route(pathname, handle)
console.log("About to route a request for :"+pathname);
if(typeof handle[pathname]==='function')
handle[pathname]();
else
console.log("No request handler for "+pathname);
sleep(10000);
console.log("Exiting router");
function sleep(milliSeconds)
var startTime = new Date().getTime(); // get the current time
while (new Date().getTime() < startTime + milliSeconds); // hog cpu
exports.route=route;
此代码被用作另一个“服务器”脚本的回调,我从浏览器调用该脚本。我希望一旦我同时向我的服务器脚本发出 100 个请求,我会在 10 秒后得到并行的 100 个响应。但是这段代码会一一遍历请求。这肯定失败了 node.js 背后的哲学,对吗??当我在 Java servlet 中编写如此糟糕的代码并在 Tomcat 上运行时,甚至不会发生这种情况!
在这种情况下的另一个观察结果是请求没有按时间顺序处理 - 它们是随机执行的。这对我来说听起来不太好!!
我认为我的代码存在一些问题 - 请帮助我理解这里的概念,并回答我的 2 个查询(另一个关于年表的查询)。
谢谢!
【问题讨论】:
***.com/questions/5670190/… 【参考方案1】:我预计一旦我同时向我的服务器脚本发出 100 个请求,我会在 10 秒后得到并行的 100 个响应。但是这段代码会一一遍历请求。
是的。 Node 严格来说是单线程的,因此每个请求都将串行运行。 JavaScript 代码中没有并行性(尽管计算机的底层 I/O 子系统可能是并行执行的)。
这肯定违背了 node.js 背后的理念,对吧??
没有。 node.js 的理念是在 I/O 事件准备就绪后尽快执行事件处理程序。
请注意,您的“睡眠”功能并没有真正进入睡眠状态,而是与 CPU 挂钩 - 因为节点是单线程的,所以所有其他操作都会阻塞 CPU 处理代码 - 如果您的代码正在执行一些实际操作,也会发生同样的情况CPU 密集型操作。但是,如果您的代码改为执行 I/O 操作(并且设计正确),那么 node 将围绕您的 I/O 阻塞代码安排其他操作。这样想——node.js 防止代码阻塞 I/O,而不是阻塞 CPU 使用。如果您的代码是 CPU 密集型的,并且您担心它会阻塞其他处理程序,那么您必须将其设计为让给事件循环以让其他处理程序运行。
在这种情况下的另一个观察结果是请求没有按时间顺序处理 - 它们是随机执行的。
是的,这是可能的。您必须记住,node.js 本质上只是一种将“事件处理程序”附加到感兴趣的 I/O 事件的方法。这些 I/O 事件由底层操作系统中的操作触发(例如,已建立套接字连接、已完成文件读取等),并且 node.js 会调用您的处理程序作为响应。
由于操作系统会自行“内部记录”事情的实际发生时间以及它认为它们何时可用于“用户空间”进程,因此您预计它们发生的时间与计算机说的时间之间可能存在差异它们实际上发生了。此外,我不认为该节点(甚至操作系统)在调度事件时保证“公平”。
【讨论】:
这是否也意味着,我不应该将 Node.js 用于 CPU 密集型程序? 不一定,这只是意味着您应该了解 CPU 密集型例程的含义,并计划将它们从节点事件循环中“卸载”(或将其分解为更小的部分),如果您怀疑它们会干扰 I/O。以上是关于Node.js 非阻塞行为的新手查询的主要内容,如果未能解决你的问题,请参考以下文章
Node.js 回调函数 1) 阻塞 ,同步 2) 非阻塞 ,异步.
JavaScript 中的事件循环和 Node.js 中的异步非阻塞 I/O 有啥区别?