我壮壮壮 2019-06-29
这篇译章探究了NodeJS的架构和单线程事件循环模型。我们将在本文中讨论“NodeJS如何在底层工作,它遵循什么类型的处理模型,NodeJS如何使用单线程模型处理并发请求”等内容。
正如我们刚才说的,NodeJS使用的是“单线程事件循环模型”的架构去处理多个并发的客户端请求的。
有许多Web应用程序技术,如JSP,Spring MVC,ASP.NET等。但所有这些技术都遵循“多线程请求 - 响应”架构来处理多个并发客户端。
我们已经熟悉“多线程请求 - 响应”架构,因为它被大多数Web应用程序框架使用。 但是为什么NodeJS选择了不同的架构来开发Web应用程序。多线程和单线程事件循环体系结构之间的主要区别是什么?
NodeJS使用“单线程事件循环模型”架构来处理多个并发客户端。然而它是如何真正处理并发客户端请求且不使用多个线程。什么是事件循环模型?我们将逐一讨论这些概念。
在讨论“单线程事件循环”架构之前,首先我们将介绍著名的“多线程请求 - 响应”架构。
任何非NodeJS开发的Web应用程序通常都遵循“多线程请求 - 响应”模型。我们可以将此模型称为请求/响应模型。
客户端向服务器发送请求,然后服务器根据客户端请求进行一些处理,准备响应并将其发送回客户端。
该模型使用HTTP协议。由于HTTP是无状态协议,因此该请求/响应模型也是无状态模型。所以我们可以将其称为请求/响应无状态模型。
但是,此模型使用多线程来处理并发客户端请求。 在讨论这个模型内部之前,首先要看下面的内容。
Web服务器处理请求步骤:
服务器为所有客户端执行以上步骤,为每一个客户端请求创建一个线程。
图表说明:
Web服务器逐个接收这些请求:
Web服务器拾取Client-1的请求Request-1,从线程池中拾取一个线程T-1并将此请求分配给线程T-1
Web服务器拾取Client-2的请求Request-2,从线程池中拾取一个线程T-2并将此请求分配给线程T-2
Web服务器拾取Client-n的请求Request-n,从线程池中拾取一个线程T-n并将此请求分配给线程T-n
如果'n'大于'm'(大多数时候,它是真的),则在使用完所有的m个线程之后,剩余的客户端请求会在队列中等待。
如果这些线程中有大量的阻塞IO操作(例如:和数据库、文件系统、外部服务等交互),那么剩余的客户端也会等待更长的时间。
请求/响应无状态模型的缺点:
NodeJS不遵循请求/响应多线程无状态模型。 它采用单线程与事件循环模型。 NodeJS的处理模型主要基于Javascript基于事件的模型和Javascript回调机制。
因为NodeJS遵循的架构,它可以非常轻松地处理越来越多的并发客户端请求。 在讨论这个模型内部之前,首先要看下面的图表。
我试图设计这个图来解释NodeJS内部的每一点。
NodeJS的处理模型主要核心是“事件循环(Event Loop)”。如果我们理解这一点,那么很容易理解NodeJS的内部架构的。
如果有,则会从事件队列中拾取一个客户端请求:
如果该客户端请求需要一些阻塞IO操作,例如与数据库,文件系统,外部服务交互,那么它将遵循不同的方法:
图表说明:
NodeJS的事件循环从队列中开始拾取这些请求:
事件循环拾取Client-1的请求Request-1
事件循环拾取Client-2的请求Request-2
事件循环拾取Client-n的请求Request-n
事件循环依次将此Response-n发送到Client-n
此处客户端请求是对一个或多个JavaScript函数的调用,因为JavaScript函数可以调用其他函数或可以利用其回调函数性质。
此所以每个客户端的请求处理都看起来向这样:
例如:
function1(function2,callback1); function2(function3,callback2); function3(input-params);
NodeJS的单线程事件循环的优势
NodeJS使用到了较少的线程,所以资源和内存的使用较少
原文地址: NodeJS Architecture – Single Threaded Event Loop