节点事件循环混淆

时间:2015-09-08 22:54:03

标签: node.js asynchronous nonblocking

我有点困惑,不知道我是否完全理解nodeJS事件循环/非阻塞I / O概念。

我们在服务器中说:

app.get('/someURL', AuthHandler.restrict, MainHandler.findAllStocksFromUser);

findAllStocksFromUser()的定义如下:

findAllStocksFromUser(req,res) {
     /* Do some terribly inefficient, heavy computation*/
     res.send(/*return something*/);
}

所以现在让我们说5个请求进来。据我所知,随着每个请求的进入,回调(在本例中为findAllStocksFromUser())被添加到eventloop队列中,并且每次打勾都会调用回调。

问题:

  1. “非常低效,繁重的计算”不会影响服务器在进入请求时有效接收请求并立即将其回调添加到队列的能力,对吗?

  2. 但是“非常低效,繁重的计算”会阻止其他回调,直到它完成并导致服务器以这种方式效率低下,对吧?

3 个答案:

答案 0 :(得分:2)

在node.js中,您的Javascript是单线程的。这意味着一次只能运行一个Javascript。因此,一旦请求处理程序开始运行,它将一直运行,直到它完全完成并返回到调用它的系统或直到它启动异步操作(数据库,文件,网络等...)然后返回到调用它的系统。只有这样,其他请求才能开始处理。

所以,如果你的计算量很大"是真正的大量同步Javascript运行,然后在运行时没有其他请求将处理。如果那"繁重的计算"实际上有很多异步操作,然后其他请求将在处理程序等待异步操作的响应时运行。

现在,针对您的具体问题:

  

所以现在让我们说5个请求进来。据我了解,每个请求   请求进来,回调,在这种情况下   将findAllStocksFromUser()添加到eventloop队列中,并使用   每个滴答,都会调用回调。

这不是很正确。传入的请求已排队,但排队的级别远低于排队回调的级别。它在您的服务器的Javascript部分甚至看到请求之前排队(在本地代码中)。

  

非常低效,繁重的计算"不会影响到   服务器在进入时有效接收请求的能力   立即将他们的回调添加到队列中,对吗?

传入的请求将由底层TCP基础结构或node.js中的本机代码排队,这些代码实现了您的服务器(它不是在单线程JS中运行)。因此,长时间运行的Javascript不会阻止传入的请求排队(除非某些内部队列填满)。

  

但是非常低效,繁重的计算"会阻止   其他回调,直到它完成并导致服务器   以这种方式效率低下,对吗?

正确。如果这种低效,繁重的计算是同步代码,则它会一直运行直到完成,并且在运行时没有其他请求运行。

node.js中重度计算代码的常用解决方案是重新设计它以便更快地运行,或者在可能的情况下使用异步操作,或者将其移出主进程并启动子进程或子进程群集处理繁重的计算。然后,这允许您的主请求处理程序将此繁重的计算视为异步操作,并允许在主node.js线程之外执行繁重的工作时运行其他操作。

虽然这有时会更多编码工作,但也可以将长时间运行的计算分解为块,以便可以执行大量工作,然后使用setImmediate()来安排下一部分工作,允许其他工作在您的工作块之间处理的排队项目。由于现在很快就建立了一个工作池,你把工作分开了,我可能会喜欢这种方法,因为它也可以让你更好地利用多个CPU并节省它" chunking"的复杂性工作和编写代码以有效地处理这种方式。

答案 1 :(得分:1)

是的,它会影响它。 Node.js是单线程的。这意味着"非常低效,繁重的计算"将在处理时阻止所有内容

这很容易测试:发送多个请求并查看其响应时间。或者只是发送一个非常大的JSON文件(它必须被解析,这可能很慢),并再次测量响应时间。

您可以将计算分解为更小的块以提高效率。

答案 2 :(得分:0)

是的,这会导致服务器效率低下。由于javascript事件循环在单个线程上运行,因此对服务器的第一个请求将阻止处理所有其他请求。

所有其他请求必须等待,因为事件循环被第一个 findAllStocksFromUser 任务阻止才能到达服务器。