摘要:客戶端可能需要等待服務(wù)器釋放可用的線程去處理其請求處理阻塞式的任務(wù)時浪費時間的架構(gòu)單線程事件循環(huán)不遵循請求響應(yīng)多線程無狀態(tài)模型。它采用單線程與事件循環(huán)模型。
這篇譯章探究了NodeJS的架構(gòu)和單線程事件循環(huán)模型。我們將在本文中討論“NodeJS如何在底層工作,它遵循什么類型的處理模型,NodeJS如何使用單線程模型處理并發(fā)請求”等內(nèi)容。
NodeJS 單線程事件循環(huán)模型正如我們剛才說的,NodeJS使用的是“單線程事件循環(huán)模型”的架構(gòu)去處理多個并發(fā)的客戶端請求的。
有許多Web應(yīng)用程序技術(shù),如JSP,Spring MVC,ASP.NET等。但所有這些技術(shù)都遵循“多線程請求 - 響應(yīng)”架構(gòu)來處理多個并發(fā)客戶端。
我們已經(jīng)熟悉“多線程請求 - 響應(yīng)”架構(gòu),因為它被大多數(shù)Web應(yīng)用程序框架使用。 但是為什么NodeJS選擇了不同的架構(gòu)來開發(fā)Web應(yīng)用程序。多線程和單線程事件循環(huán)體系結(jié)構(gòu)之間的主要區(qū)別是什么?
NodeJSNodeJS使用“單線程事件循環(huán)模型”架構(gòu)來處理多個并發(fā)客戶端。然而它是如何真正處理并發(fā)客戶端請求且不使用多個線程。什么是事件循環(huán)模型?我們將逐一討論這些概念。
在討論“單線程事件循環(huán)”架構(gòu)之前,首先我們將介紹著名的“多線程請求 - 響應(yīng)”架構(gòu)。
傳統(tǒng)的Web應(yīng)用處理模型任何非NodeJS開發(fā)的Web應(yīng)用程序通常都遵循“多線程請求 - 響應(yīng)”模型。我們可以將此模型稱為請求/響應(yīng)模型。
客戶端向服務(wù)器發(fā)送請求,然后服務(wù)器根據(jù)客戶端請求進行一些處理,準備響應(yīng)并將其發(fā)送回客戶端。
該模型使用HTTP協(xié)議。由于HTTP是無狀態(tài)協(xié)議,因此該請求/響應(yīng)模型也是無狀態(tài)模型。所以我們可以將其稱為請求/響應(yīng)無狀態(tài)模型。
但是,此模型使用多線程來處理并發(fā)客戶端請求。 在討論這個模型內(nèi)部之前,首先要看下面的內(nèi)容。
請求/響應(yīng)模型處理的步驟:客戶端發(fā)送一個請求到Web服務(wù)器
Web服務(wù)器內(nèi)部維護一個有限的線程池,以便在客戶端請求提供服務(wù)
Web服務(wù)器處于無限循環(huán)中并等待客戶端傳入請求
Web服務(wù)器處理請求步驟:
接收到一個客戶端請求
從線程池中選擇一個線程
將此線程分配給客戶端請求
此線程讀取客戶端請求,處理客戶端請求,執(zhí)行阻塞的IO操作(如果需要)和準備響應(yīng)
此線程將準備好的請求發(fā)送回Web服務(wù)器
Web服務(wù)器又將此響應(yīng)發(fā)送到相應(yīng)的服務(wù)器
服務(wù)器為所有客戶端執(zhí)行以上步驟,為每一個客戶端請求創(chuàng)建一個線程。
圖表說明:
Client-1, Client-2, ..., Client-n是同時發(fā)送請求到Web服務(wù)器的客戶端應(yīng)用
Web服務(wù)器內(nèi)部維護著一個有限的線程池,線程池中線程數(shù)量為m個
Web服務(wù)器逐個接收這些請求:
Web服務(wù)器拾取Client-1的請求Request-1,從線程池中拾取一個線程T-1并將此請求分配給線程T-1
線程T-1讀取Client-1的請求Request-1, 并處理該請求
該請求無阻塞IO處理
處理完必要的步驟后準備將Response-1發(fā)送回客戶端
Web服務(wù)器又將此Response-1發(fā)送到Client-1
Web服務(wù)器拾取Client-2的請求Request-2,從線程池中拾取一個線程T-2并將此請求分配給線程T-2
線程T-2讀取Client-2的請求Request-2, 并處理該請求
該請求無阻塞IO處理
處理完必要的步驟后準備將Response-2發(fā)送回客戶端
Web服務(wù)器又將此Response-2發(fā)送到Client-2
Web服務(wù)器拾取Client-n的請求Request-n,從線程池中拾取一個線程T-n并將此請求分配給線程T-n
線程T-n讀取Client-n的請求Request-n, 并處理該請求
Request-n需要大量的阻塞IO和計算操作
線程T-n需要更多時間與外部系統(tǒng)(SQL, File System)交互,執(zhí)行必要步驟并準備Response-n并將其發(fā)送回服務(wù)器
Web服務(wù)器又將此Response-n發(fā)送到Client-n
如果"n"大于"m"(大多數(shù)時候,它是真的),則在使用完所有的m個線程之后,剩余的客戶端請求會在隊列中等待。
如果這些線程中有大量的阻塞IO操作(例如:和數(shù)據(jù)庫、文件系統(tǒng)、外部服務(wù)等交互),那么剩余的客戶端也會等待更長的時間。
一旦線程池中的線程空閑且可用于下一個任務(wù),服務(wù)器就會拾取這些線程并將它們分配給剩余的客戶端請求。
每個線程都會使用到許多資源,如內(nèi)存等。因此,在將這些線程從忙狀態(tài)轉(zhuǎn)到等待狀態(tài)之前,它們應(yīng)該釋放所有獲取的資源。
請求/響應(yīng)無狀態(tài)模型的缺點:
在處理越來越多的并發(fā)客戶端請求時會變得棘手
當(dāng)客戶端請求增加時,線程也會越來越多,最后它們會占用更多內(nèi)存。
客戶端可能需要等待服務(wù)器釋放可用的線程去處理其請求
處理阻塞式的IO任務(wù)時浪費時間
NodeJS的架構(gòu) - 單線程事件循環(huán)NodeJS不遵循請求/響應(yīng)多線程無狀態(tài)模型。 它采用單線程與事件循環(huán)模型。 NodeJS的處理模型主要基于Javascript基于事件的模型和Javascript回調(diào)機制。
因為NodeJS遵循的架構(gòu),它可以非常輕松地處理越來越多的并發(fā)客戶端請求。 在討論這個模型內(nèi)部之前,首先要看下面的圖表。
我試圖設(shè)計這個圖來解釋NodeJS內(nèi)部的每一點。
NodeJS的處理模型主要核心是“事件循環(huán)(Event Loop)”。如果我們理解這一點,那么很容易理解NodeJS的內(nèi)部架構(gòu)的。
單線程事件循環(huán)模型的處理步驟客戶端發(fā)送請求到Web服務(wù)器
NodeJS的Web服務(wù)器在內(nèi)部維護一個有限的線程池,以便為客戶端請求提供服務(wù)
NodeJS的Web服務(wù)器接收這些請求并將它們放入隊列中。 它被稱為“事件隊列”
NodeJS的Web服務(wù)器內(nèi)部有一個組件,稱為“事件循環(huán)”,它使用無限循環(huán)來接收請求并處理它們。
事件循環(huán)只使用到了一個線程,它是NodeJS的處理模型的核心
事件循環(huán)回去檢查是否有客戶端的請求被放置在事件隊列中。如果沒有,會一直等待事件隊列中存在請求。
如果有,則會從事件隊列中拾取一個客戶端請求:
開始處理客戶端請求
如果該客戶端請求不需要任何阻塞IO操作,則處理所有內(nèi)容,準備響應(yīng)并將其發(fā)送回客戶端
如果該客戶端請求需要一些阻塞IO操作,例如與數(shù)據(jù)庫,文件系統(tǒng),外部服務(wù)交互,那么它將遵循不同的方法:
從內(nèi)部線程池檢查線程可用性
獲取一個線程并將此客戶端請求分配給該線程
該線程負責(zé)接收該請求,處理該請求,執(zhí)行阻塞IO操作,準備響應(yīng)并將其發(fā)送回事件循環(huán)
事件循環(huán)依次將響應(yīng)發(fā)送到相應(yīng)的客戶端
圖表說明:
Client-1, Client-2, ..., Client-n是同時發(fā)送請求到Web服務(wù)器的客戶端應(yīng)用
Web服務(wù)器內(nèi)部維護著一個有限的線程池,線程池中線程數(shù)量為m個
NodeJS的Web服務(wù)器接收到Client-1, Client-2, ..., Client-n的請求后,將請求放入到事件隊列中
NodeJS的事件循環(huán)從隊列中開始拾取這些請求:
事件循環(huán)拾取Client-1的請求Request-1
檢查Client-1 Request-1是否確實需要任何阻塞IO操作,或者需要更多時間來執(zhí)行復(fù)雜的計算任務(wù)
由于此請求是簡單計算和非阻塞IO任務(wù),因此不需要多帶帶的線程來處理它
事件循環(huán)處理該請求所需要的操作,準備其響應(yīng)Response-1
事件循環(huán)發(fā)送Response-1到Client-1
事件循環(huán)拾取Client-2的請求Request-2
檢查Client-2 Request-2是否需要任何阻塞IO操作或花費更多時間來執(zhí)行復(fù)雜的計算任務(wù)
由于此請求是簡單計算和非阻塞IO任務(wù),因此不需要多帶帶的線程來處理它
事件循環(huán)處理該請求所需要的操作,準備其響應(yīng)Response-2
事件循環(huán)發(fā)送Response-2到Client-2
事件循環(huán)拾取Client-n的請求Request-n
檢查Client-n Request-n是否需要任何阻塞IO操作或花費更多時間來執(zhí)行復(fù)雜的計算任務(wù)
由于此請求有非常復(fù)雜的計算或阻塞IO任務(wù),因此事件循環(huán)不會處理此請求
事件循環(huán)從內(nèi)部線程池中獲取線程T-1,并將此Client-n Request-n分配給線程T-1
線程T-1讀取并處理Request-n,執(zhí)行必要的阻塞IO或計算任務(wù),最后準備響應(yīng)Response-n
線程T-1將此Response-n發(fā)送到事件循環(huán)
事件循環(huán)依次將此Response-n發(fā)送到Client-n
此處客戶端請求是對一個或多個JavaScript函數(shù)的調(diào)用,因為JavaScript函數(shù)可以調(diào)用其他函數(shù)或可以利用其回調(diào)函數(shù)性質(zhì)。
此所以每個客戶端的請求處理都看起來向這樣:
例如:
function1(function2,callback1); function2(function3,callback2); function3(input-params);
NodeJS的單線程事件循環(huán)的優(yōu)勢
處理越來越多的并發(fā)客戶端請求非常容易
因為事件循環(huán)的存在,即使我們的NodeJS應(yīng)用接收到了越來越多的并發(fā)請求,我們也不需要去新建很多的線程
NodeJS使用到了較少的線程,所以資源和內(nèi)存的使用較少
原文地址: NodeJS Architecture – Single Threaded Event Loop
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/100107.html
摘要:概述本篇主要介紹的運行機制單線程事件循環(huán)結(jié)論先在中利用運行至完成和非阻塞完成單線程下異步任務(wù)的處理就是先處理主模塊主線程上的同步任務(wù)再處理異步任務(wù)異步任務(wù)使用事件循環(huán)機制完成調(diào)度涉及的內(nèi)容有單線程事件循環(huán)同步執(zhí)行異步執(zhí)行定時器的事件循環(huán)開始 1.概述 本篇主要介紹JavaScript的運行機制:單線程事件循環(huán)(Event Loop). 結(jié)論先: 在JavaScript中, 利用運行至...
摘要:使用了一個事件驅(qū)動非阻塞式的模型,使其輕量又高效。的包管理器,是全球最大的開源庫生態(tài)系統(tǒng)。按照這個定義,之前所述的阻塞,非阻塞,多路復(fù)用信號驅(qū)動都屬于同步。 系列文章 Nodejs高性能原理(上) --- 異步非阻塞事件驅(qū)動模型Nodejs高性能原理(下) --- 事件循環(huán)詳解 前言 終于開始我nodejs的博客生涯了,先從基本的原理講起.以前寫過一篇瀏覽器執(zhí)行機制的文章,和nodej...
摘要:的單線程,與它的用途有關(guān)。特點的顯著特點異步機制事件驅(qū)動。隊列的讀取輪詢線程,事件的消費者,的主角。它將不同的任務(wù)分配給不同的線程,形成一個事件循環(huán),以異步的方式將任務(wù)的執(zhí)行結(jié)果返回給引擎。 這兩天跟同事同事討論遇到的一個問題,js中的event loop,引出了chrome與node中運行具有setTimeout和Promise的程序時候執(zhí)行結(jié)果不一樣的問題,從而引出了Nodejs的...
摘要:異步和事件驅(qū)動注本文是對眾多博客的學(xué)習(xí)和總結(jié),可能存在理解錯誤。接觸有兩個月,對的兩大特性一直有點模糊,即異步和事件驅(qū)動。 nodejs 異步I/O和事件驅(qū)動 注:本文是對眾多博客的學(xué)習(xí)和總結(jié),可能存在理解錯誤。請帶著懷疑的眼光,同時如果有錯誤希望能指出。 接觸nodejs有兩個月,對nodejs的兩大特性一直有點模糊,即異步IO和事件驅(qū)動。通過對《深入淺出nodejs》和幾篇博客的閱...
閱讀 2972·2023-04-25 19:20
閱讀 839·2021-11-24 09:38
閱讀 2115·2021-09-26 09:55
閱讀 2472·2021-09-02 15:11
閱讀 2156·2019-08-30 15:55
閱讀 3643·2019-08-30 15:54
閱讀 3178·2019-08-30 14:03
閱讀 2992·2019-08-29 17:11