明确解决“阻止代码”?
我正在从Node Beginner Book和随后的电子书购买中学习node.js。 在这本书中,Manuel Kiessling解释说,像这样的一行代码:
fs.readFileSync(blah);
将阻止整个节点进程和所有请求进来。这对于多用户网站来说真是太糟糕了!
这就是基斯林使用的例子:
exec("ls -lah", function( error, stdout, stderr ) { response.writeHead(200, {"Content-Type": "text/plain"}); response.write(stdout); response.end(); });
这是欺骗我的代码。 他说ls -lah
很容易被find / -name "*"
或者数据库查找等更耗时的操作所取代。 我认为昂贵的阻塞操作会以某种方式明确地在后台运行,因为asynchronouscallback。
所以我必须用这个代码来testing我的理论:
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);
问题是,无论我在哪里睡觉,它仍然阻塞节点事件循环。 callback不能解决阻塞问题。 SO的好用户也在评论中告诉我这一点。
那么exec
如何做呢? 我很困惑,所以我去看了github上的subprocess代码 。 我发现exec
调用spawn
! 它使一个孩子的过程! 谜团已揭开。 asynchronous代码不能“解决”阻塞问题,产卵。
这导致我的问题。 expression方式不知何故解决阻塞问题,还是你还要担心呢?
PS:这个问题是一个重大的重写。 我想请求下面的SO用户的赦免,并感谢他们对我的耐心。 我在这里肯定学到了一些东西。
有人发表了关于理解节点js事件循环的评论。 对,就是这样。 如果将其封装在asynchronous调用中,则可以发出阻塞调用,因为您没有阻止节点事件循环。
如果你用asynchronous调用包装同步调用,你仍然会遇到阻塞。 例如,如果你写这样的东西:
fs.readFile("file1.txt", function(err, data1) { var data2 = fs.readFileSync("file2.txt"); });
这个进程在读取file1.txt时不会被阻塞,因为你正在使用一个asynchronous调用,但是一旦它读完file1并且到达它读取file2的那一行, 它就会被阻塞 。
通过在asynchronous/非阻塞调用中发出同步/阻塞调用,您只会延迟阻塞。
你是正确的阻止整个网站是非常糟糕的,这就是为什么你不应该非常频繁地发出阻塞呼叫。 由于node.js是从头开始编写的,因此大多数I / O调用默认是asynchronous的,您应该尽可能使用这些而不是同步调用。
问题是,expression是否自动为你处理,还是你还要担心呢?
你还是要担心。
问题是,expression是否自动为你处理,还是你还要担心呢?
你还是要担心。 NodeJS是单线程的,这意味着每一个同步操作都会完全阻塞它,不pipe它在哪里被调用。 Express或任何其他框架都不能在不阻止服务器的情况下使用同步操作。 简单
var x = 1;
已经阻塞了整个服务器,直到完成创build新variables并为其分配新的值。
asynchronous体系结构的重点在于它比线程更高效。 不要被愚弄,因为没有隔离,asynchronous编程就更困难。 如果一个线程失败其他工作,而在asynchronous服务器一个例外可以打破整个服务器。
问题是你可以阻止主节点事件循环!
这句话表明,NodeJS比主事件循环更重要。 这不是真的。 每个代码都在主循环中调用。
也看看这个:
事件循环与multithreading阻塞IO
任何对非asynchronous函数的调用都会“阻塞”,即使它被另一个函数包装了。 唯一的例外是如果包装函数可以推迟到另一个线程/进程的处理(例如,像cluster
API)。