我正在学习Node Beginner Book中的node.js和随后的电子书购买。在这本书中,Manuel Kiessling解释了一系列像这样的阻塞代码:
fs.readFileSync(blah);
将阻止整个节点进程和所有请求进入。对于多用户网站来说非常糟糕!
这是一个例子,Kiessling使用:
exec("ls -lah", function( error, stdout, stderr ) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write(stdout);
response.end();
});
这是欺骗我的代码。他说,ls -lah
可以很容易地用更耗时的操作替换,如find / -name "*"
或数据库查找。我认为由于异步回调,昂贵的阻塞操作会以某种方式在后台显式运行。
所以我用这段代码来测试我的理论:
var http = require("http");
var url = require("url");
badSleep = function(ms) {
var now = new Date();
var finishAtDate = now.getTime() + ms;
console.log("CPU burning sleep for " + ms + " milliseconds");
while(new Date() < finishAtDate) {
// do nothing
}
};
asyncWrapper = function(callback) {
//badSleep(3000);
callback();
}
http.createServer(function(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Serve up " + pathname);
if (pathname == '/favicon.ico') {
response.writeHead(404);
response.end();
} else {
asyncWrapper(function() {
badSleep(3000);
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("\nI was wrong " + new Date());
response.end();
});
}
}).listen(8888);
问题是,无论我把睡眠放在哪里,仍会阻止节点事件循环。回调确实不解决阻塞问题。 SO的好用户也在评论中告诉了我。
那么exec
怎么做呢???我很困惑,于是我去看了child-process code at github。我发现exec
来电spawn
!!!这是一个孩子的过程!谜团已揭开。异步代码没有“解决”阻塞问题,spawn会这样做。
这引出了我的问题。是否以某种方式解决了阻塞问题,还是你还要担心它?
答案 0 :(得分:3)
有人发表了关于理解-node-js-event-loop的评论。是 究竟。如果将其包装在异步中,则可以发出阻塞调用 调用,因为你没有阻塞节点事件循环。
如果使用异步调用包装同步调用,您仍将遇到阻塞。例如,如果你写这样的东西:
fs.readFile("file1.txt", function(err, data1) {
var data2 = fs.readFileSync("file2.txt");
});
由于您正在使用异步调用,因此在读取file1.txt时不会阻止该进程,但是,只要它完成读取file1并且它到达读取file2的行然后它将阻塞即可。
通过在异步/非阻塞调用中发出同步/阻塞调用,您只能延迟阻止。
对于整个网站的阻止非常糟糕,这是正确的,这就是为什么不应经常发出阻止调用的原因。由于node.js是从头开始编写的,因此默认情况下大多数I / O调用都是异步的,您应该尽可能多地使用它们而不是同步调用。
问题是,是否会自动为您表达或处理此问题 你还需要担心吗?
你还是要担心它。
答案 1 :(得分:2)
问题是,是否会自动为您表达或处理此问题 你还要担心吗?
你还是要担心它。 NodeJS是单线程的,这意味着无论在何处调用,每个同步操作都将完全阻止它。 Express和任何其他框架都不能在不阻塞服务器的情况下使用同步操作。简单
var x = 1;
已经阻止整个服务器,直到它完成创建新变量并为其分配新值。
异步架构的重点在于它比线程更有效。并且不要被愚弄,异步编程比线程更难,因为没有隔离。如果一个线程失败,其他线程仍然有效,而在异步服务器中,一个例外可能会破坏整个服务器。
问题是您可以阻止主节点事件循环!
这句话表明NodeJS比主事件循环更多。这不是真的。每个代码都在主循环内调用。
还看看这个:
答案 2 :(得分:1)
对非异步函数的任何调用都将“阻塞”,即使它被包装在另一个函数中。唯一的例外是如果包装函数可以将处理推迟到另一个线程/进程(例如,像cluster
API)。