Node.js 如何处理并发
Node.js是一个基于Chrome的V8引擎构建的开源跨平台运行环境。它被用于开发高度可扩展的后端和服务器端应用程序。
Node.js采用了单线程事件循环架构,并且具有异步性质。这是Node.js能够轻松处理多个并发请求的两个主要原因,也是开发此类应用程序的明显选择。
Node.js的工作原理
Node.js工作 异步地 换句话说,当操作系统有一个I/O密集型的请求时,它不会阻塞来自客户端的传入请求。相反,它会将这个I/O请求传递给内部的C++线程,并从事件队列中选择下一个任务。
注意: 内部的C++线程可能有一个,也可能没有,但这不是这里关注的问题。
事件队列只是一个按照接收顺序存储传入请求的队列。当事件循环可用时,它将这些请求传递给事件循环。对于每个I/O请求,事件循环会接收并将其传递给内部的C++线程进行处理,然后自己变得可用来处理其他请求。然后,它使用JavaScript的回调函数的概念来接收之前发送给内部C++线程进行处理的任务的响应,并将其传递给客户端。
让我们通过一个示例来理解这个过程:
示例1:传统Web架构
在这里,我们有4个console.log()语句,按照1到4的顺序排列。假设这是一个传统的基于架构的应用程序,输出会像这样。
输出:
解释: 在这里,“Hey I am Line number 4”会先执行,因为它在函数调用之前。然后调用函数。接下来会打印出“Hey I am Line number 1”,并将传递给setTimeout的回调函数添加到浏览器的宏任务队列中,分别打印出“Hey I am Line number 3”,然后当setTimeout的第二个参数指定的时间到达时,JS事件循环会从队列中取出回调函数并执行,从而打印出“Hey I am Line number 2” 。
示例2:Node.js应用程序
这里有4个console.log()语句的顺序是从1到4。假设这是一个单线程非阻塞的应用程序,输出结果将会是这样的。
输出结果:
解释: 这里,”Hey I am Line number 4″ 将首先执行,因为它在函数调用之前。然后调用函数。然后将打印 “Hey I am Line number 1″,应用程序将因为函数调用而进入2秒(2000ms)的超时。现在,当应用程序等待2秒时,它不会阻塞后续请求,而是会处理下一个请求,因此打印 “Hey I am Line number 3″。一旦超时结束,将会执行这几行,并将 “Hey I am Line number 2” 打印到控制台。
这样,事件循环永远不会被特定请求占用或阻塞。这就是为什么 Node.js 在处理多个用户请求方面比传统的 web 服务器具有竞争优势,即并发性。