在NodeJS中的不同path上的并行请求:长时间运行path1阻塞其他path

我正在尝试简单的NodeJS应用程序,以便我可以了解asynchronous性质。

但是我的问题是一旦我从浏览器中点击“ /home ”就等待响应,同时当“ / ”被点击时,它首先等待“ /home ”的响应,然后响应“ / ”请求。

我担心的是,如果其中一个请求需要大量处理,同时我们不能再请求另一个呢? 它是否正确?

  app.get("/", function(request, response) { console.log("/ invoked"); response.writeHead(200, {'Content-Type' : 'text/plain'}); response.write('Logged in! Welcome!'); response.end(); }); app.get("/home", function(request, response) { console.log("/home invoked"); var obj = { "fname" : "Dead", "lname" : "Pool" } for (var i = 0; i < 999999999; i++) { for (var i = 0; i < 2; i++) { // BS }; }; response.writeHead(200, {'Content-Type' : 'application/json'}); response.write(JSON.stringify(obj)); response.end(); }); 

好问题,现在,虽然Node.js具有asynchronous性质,但是这段代码:

 for (var i = 0; i < 999999999; i++) { for (var i = 0; i < 2; i++) { // BS }; }; 

实际上不是asynchronous阻塞节点主线程。 因此,所有其他请求必须等到这个大的for循环结束。

为了同时进行一些繁重的计算,我build议使用setTimeoutsetInterval来实现您的目标:

 var i=0; var interval = setInterval(function() { if(i++>=999999999){ clearInterval(interval); } //do stuff here },5); 

有关更多信息,我build议search“Node.js事件循环”

正如Stasel 所说 ,运行的代码会阻塞事件循环。 基本上每当javascript在服务器上运行,没有别的运行。 asynchronousI / O事件(如磁盘I / O)可能在后台处理,但是它们的处理程序/callback将不会被调用,除非您的同步代码已经完成运行。 基本上,一旦完成,节点将检查待处理的事件并分别调用它们的处理程序。

你实际上有几个select来解决这个问题。

  1. 将工作分解,让待处理的事件在两者之间执行。 这与Stasel的build议几乎相同,除了单次迭代之间的5ms是巨大的。 对于像999999999项目,这需要永远。 首先,我build议批处理循环大约一段时间,然后安排下一批处理。 基本上是在处理待处理的I / O事件之后进行调度,所以如果没有新的I / O事件要处理(就像没有新的http请求一样),那么它将立即执行。 速度够快 现在的问题是,我们应该为每个批次/迭代进行多less处理。 我build议先测量一下手动平均多less,以及约50ms的工作时间表。 例如,如果你已经实现了1000个项目需要100毫秒。 然后让它处理500个项目,所以它将是50ms。 你可以进一步细分,但是分解越多,花费的时间就越多。 所以要小心。 另外,由于你正在处理大量的项目,尽量不要做太多垃圾,所以垃圾收集器不会太多的阻止。 在这个不太相似的问题中 ,我已经解释了如何在不阻塞事件循环的情况下将10000个文档插入到MongoDB中。

  2. 使用线程。 实际上有一些很好的线程实现,你不会用自己的脚步射击自己。 对于这种情况,这是一个好主意,如果你正在寻找性能巨大的进程,因为如上所述,要执行CPU绑定的任务,并且在同一个进程中发生的其他事情发挥不错,asynchronous事件是完美的数据绑定任务而不是CPU绑定任务。 有可以使用的nodejs-threads-a-gogo模块。 您也可以使用build立在threads-a-gogo上的node-webworker-threads ,但是使用webworker API。 还有nPool ,这个看起来不错,但不太受欢迎。 他们都支持线程池,应该直接实现一个工作队列。

  3. 做几个进程而不是线程。 这可能比线程慢,但是对于大的东西来说,仍然比在主进程中迭代要好。 有不同的方法。 使用进程会给你一个devise,你可以扩展到使用多台机器,而不是只使用多个CPU。 您可以使用作业队列(基本上每当完成要处理的任务时都从队列中抽取下一个),多进程映射减less或AWS弹性映射减less或使用nodejs群集模块。 使用集群模块,您可以侦听每个worker上的unix域套接字,并且对于每个作业只需向该套接字发送请求。 每当工作人员完成处理作业,它只会回写那个特定的请求。 你可以search这个东西,已经有很多实现和模块了。 您可以使用0MQ,rabbitMQ,节点内置的ipc,unix域套接字或redis队列进行多进程通信。