node.js单线程模型如何处理并发请求?

时间:2017-04-23 00:24:05

标签: javascript node.js

两个并发请求R1和R2来到node.js server. Node.js正在运行单线程T1。 T1需要5秒钟来处理请求R1。假设这一次 花在一些实际的大功能处理上,没有等待/ IO调用。

我的问题是 - 请求R2将在5秒后接收(一旦R1完成) 或两者(R1和R2)将以循环方式运行?

如果答案是顺序的(即R2将在5秒后被占用),我的后续问题是说我有5k http并发请求,每个请求需要2 ms,然后最后一个请求将在5k * 2ms = 10秒后提供。这不错吗?我需要在这里进行聚类吗?

2 个答案:

答案 0 :(得分:2)

  

请求download_link将在5秒后完成( var resvbTabRef = firebase.database().ref("Reservation/user") resvbTabRef.on('child_added', function(snapshot) { var user = firebase.auth().currentUser; var specialKey = snapshot.key; var fullName = snapshot.val().Name; var phnNum = snapshot.val().Phone_Number; var ResvUID = snapshot.val().uid; var ResvDate = snapshot.val().Reservation_Date; var NumPeopl = snapshot.val().Number_of_Guests; var ResvEmail = snapshot.val().Email; var ResvInfo = fullName + phnNum + ResvDate + NumPeopl + ResvUID + ResvEmail if (user.uid == ResvUID) { var resvData = ('<tr><td ="' + specialKey + '">' + specialKey + '</td><td>' + fullName + '</td><td>' + user.email + '</td><td>' + phnNum + '</td><td>' + ResvDate + '</td><td>' + NumPeopl + '</td><td>' + '<button type="button" class="btn btn-default btn-sm" data-key=' + ResvInfo.key + ' id="cancelResv"><span class="glyphicon glyphicon-remove"></span> Cancel</button>' + '</td></tr>') $("#userResvTable").append(resvData); } else { console.log("error"); } $('#userResvTable').on('click', 'button[type="button"]', function(snapshot) { $(this).closest('tr').remove(); var resvbTabRef = firebase.database().ref("Reservation/user/") resvbTabRef.once("value") .then(function(snapshot) { snapshot.forEach(function(childSnapshot) { var key = childSnapshot.key; var childData = childSnapshot.val(); var ref = firebase.database().ref("Reservation/user/" + key) return ref.remove().then(function() { console.log('OK, gone'); console.log(childData) }).catch(function(e) { console.log('OOPS, problem:' + e.message); }) childSnapshot.ref.remove(); // console.log(resTab) }) }) 完成一次)或两者(R2R1)将以循环方式运行?

是的,只有在R1完成后,如果R1同步,R2才会被占用。

简而言之,您可以谷歌R1。有很多很棒的文章解释了Node.js如何使用事件循环来处理请求。

  

事件循环允许Node.js执行非阻塞I / O操作 - 尽管JavaScript是单线程的 - 通过尽可能将操作卸载到系统内核。   (来源:https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/

Node.js是单线程的,这是正确的。如果被长时间运行的任务阻止,它就无法处理任何其他内容。在您的情况下,您应该将R2细分为较小的部分以进行异步处理,或者您可以使用child_process将操作卸载到另一个线程。

  

如果答案是顺序的(即nodejs event loop将在5秒后被占用),我的后续问题是说我有5k http并发请求,每个请求需要2 ms,然后最后一个请求将在5k *之后提供2ms = 10秒。这不错吗?我需要在这里进行聚类吗?

这取决于。 2ms实际上是计算机处理很多事情的很长时间。在进行群集之前,您应该重构代码以最小化请求处理程序中的阻塞代码,如上所述。在购买更多用于群集的服务器之前,您可以使用cluster库将应用程序克隆到其他线程,从而充分利用CPU核心。精心设计的Node.js应用程序应该能够毫无问题地处理数千个请求。否则,您可能会重新考虑Node.js是否最适合您的应用程序。

  

奖励:让我们听听Node.js的发明者 - why he created Node.js

答案 1 :(得分:1)

如果您的功能受CPU限制,那么您将占用事件循环。你有两个选择。

  1. 转换到与其他进程的不同通信模型,可能运行自己的事件循环:pre-fork或worker MPM。如果您想使用child_process
  2. ,可以在Node中生成这些流程
  3. 限制CPU处理,并发出.nextTick()以允许事件循环中的其他内容完成并稍后恢复。