主程序:
var http = require('http');
var url = require('url');
var cp = require('child_process');
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
if( pathname == '/wait' ) {
console.log("Will wait!");
cp.exec('node applications\\demo\\block.js', [], myCallback);
console.log(new Date());
}
else{
response.writeHead(200, {'Content-Type': 'text/plain'});
response.write('Hello!\n');
response.end();
}
console.log('Cool ' + (new Date()));
function myCallback(){
console.log("ok: " + (new Date()));
response.writeHead(200, {'Content-Type': 'text/plain'});
response.write('Thanks for waiting!\n');
response.end();
}
}
http.createServer(onRequest).listen(8081);
console.log('Server started');
exec
调用的block.js
是(即休眠10秒):
var startTime = new Date().getTime();
while (new Date().getTime() < startTime + 10000);
如果我访问http://localhost:8081/wait
,会进入pathname == '/wait'
的语句,并且通过exec
调用block.js
休眠10秒。这时我在休眠结束之前迅速的访问http://localhost:8081/
,迅速返回结果。这个我认为是正常的。
但是如果我同时打开三个http://localhost:8081/wait
链接,发现第一个链接大约花10秒,第二个链接大约花20秒,第三个链接大约花30秒(从console
的输出看他们是串行的)。通过任务管理器看到只多了一个node
进程(win 7操作系统,四核)。难道这三次访问exec
不应该开三个block.js
进程吗?请教该如何理解这段代码和这个现象?Nodejs
所说的能同时处理多个请求到底该如何理解呢?
附上console
输出:
Server started
Will wait!
Sun Jan 25 2015 00:59:50 GMT+0800 (中国标准时间)
Cool Sun Jan 25 2015 00:59:50 GMT+0800 (中国标准时间)
ok: Sun Jan 25 2015 01:00:01 GMT+0800 (中国标准时间)
Will wait!
Sun Jan 25 2015 01:00:21 GMT+0800 (中国标准时间)
Cool Sun Jan 25 2015 01:00:21 GMT+0800 (中国标准时间)
ok: Sun Jan 25 2015 01:00:31 GMT+0800 (中国标准时间)
Will wait!
Sun Jan 25 2015 01:00:31 GMT+0800 (中国标准时间)
Cool Sun Jan 25 2015 01:00:31 GMT+0800 (中国标准时间)
ok: Sun Jan 25 2015 01:00:41 GMT+0800 (中国标准时间)
开小窗口用curl测试,行为和预期一致
所以可以判断这是浏览器的行为
另外,一般意义上说node非阻塞不是题主的busy-wait+子进程的实现方式(动辄cpu100%完全顶不住压力),而是事件队列,单进程单线程的非阻塞,拿题主的例子改改是这样的
简单来说,就是事件(比如setTimeout,或者更常见的网络/文件IO等)来了以后,如果当前状态是空闲的,那么会立刻处理;而如果正在执行其他代码,则会推入队列中,等待执行完毕后才处理。所以微观来说,一个node进程同一时间永远最多只在处理一个请求。但由于多数业务都是IO密集型,主要瓶颈往往落在磁盘IO,数据库或其他服务的网络IO等等,实际的业务CPU运算很少,此时node多数时间都处于等待IO回调的空闲状态,因此宏观上来看一个node进程往往可以同时处理大量的业务请求