成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

NodeJS架構(gòu) - 單線程事件循環(huán)模型

leap_frog / 2026人閱讀

摘要:客戶端可能需要等待服務(wù)器釋放可用的線程去處理其請(qǐng)求處理阻塞式的任務(wù)時(shí)浪費(fèi)時(shí)間的架構(gòu)單線程事件循環(huán)不遵循請(qǐng)求響應(yīng)多線程無狀態(tài)模型。它采用單線程與事件循環(huán)模型。

這篇譯章探究了NodeJS的架構(gòu)和單線程事件循環(huán)模型。我們將在本文中討論“NodeJS如何在底層工作,它遵循什么類型的處理模型,NodeJS如何使用單線程模型處理并發(fā)請(qǐng)求”等內(nèi)容。

NodeJS 單線程事件循環(huán)模型

正如我們剛才說的,NodeJS使用的是“單線程事件循環(huán)模型”的架構(gòu)去處理多個(gè)并發(fā)的客戶端請(qǐng)求的。

有許多Web應(yīng)用程序技術(shù),如JSP,Spring MVC,ASP.NET等。但所有這些技術(shù)都遵循“多線程請(qǐng)求 - 響應(yīng)”架構(gòu)來處理多個(gè)并發(fā)客戶端。

我們已經(jīng)熟悉“多線程請(qǐng)求 - 響應(yīng)”架構(gòu),因?yàn)樗淮蠖鄶?shù)Web應(yīng)用程序框架使用。 但是為什么NodeJS選擇了不同的架構(gòu)來開發(fā)Web應(yīng)用程序。多線程和單線程事件循環(huán)體系結(jié)構(gòu)之間的主要區(qū)別是什么?

NodeJS

NodeJS使用“單線程事件循環(huán)模型”架構(gòu)來處理多個(gè)并發(fā)客戶端。然而它是如何真正處理并發(fā)客戶端請(qǐng)求且不使用多個(gè)線程。什么是事件循環(huán)模型?我們將逐一討論這些概念。

在討論“單線程事件循環(huán)”架構(gòu)之前,首先我們將介紹著名的“多線程請(qǐng)求 - 響應(yīng)”架構(gòu)。

傳統(tǒng)的Web應(yīng)用處理模型

任何非NodeJS開發(fā)的Web應(yīng)用程序通常都遵循“多線程請(qǐng)求 - 響應(yīng)”模型。我們可以將此模型稱為請(qǐng)求/響應(yīng)模型。

客戶端向服務(wù)器發(fā)送請(qǐng)求,然后服務(wù)器根據(jù)客戶端請(qǐng)求進(jìn)行一些處理,準(zhǔn)備響應(yīng)并將其發(fā)送回客戶端。

該模型使用HTTP協(xié)議。由于HTTP是無狀態(tài)協(xié)議,因此該請(qǐng)求/響應(yīng)模型也是無狀態(tài)模型。所以我們可以將其稱為請(qǐng)求/響應(yīng)無狀態(tài)模型。

但是,此模型使用多線程來處理并發(fā)客戶端請(qǐng)求。 在討論這個(gè)模型內(nèi)部之前,首先要看下面的內(nèi)容。

請(qǐng)求/響應(yīng)模型處理的步驟:

客戶端發(fā)送一個(gè)請(qǐng)求到Web服務(wù)器

Web服務(wù)器內(nèi)部維護(hù)一個(gè)有限的線程池,以便在客戶端請(qǐng)求提供服務(wù)

Web服務(wù)器處于無限循環(huán)中并等待客戶端傳入請(qǐng)求

Web服務(wù)器處理請(qǐng)求步驟:

接收到一個(gè)客戶端請(qǐng)求

從線程池中選擇一個(gè)線程

將此線程分配給客戶端請(qǐng)求

此線程讀取客戶端請(qǐng)求,處理客戶端請(qǐng)求,執(zhí)行阻塞的IO操作(如果需要)和準(zhǔn)備響應(yīng)

此線程將準(zhǔn)備好的請(qǐng)求發(fā)送回Web服務(wù)器

Web服務(wù)器又將此響應(yīng)發(fā)送到相應(yīng)的服務(wù)器

服務(wù)器為所有客戶端執(zhí)行以上步驟,為每一個(gè)客戶端請(qǐng)求創(chuàng)建一個(gè)線程。

圖表說明:

Client-1, Client-2, ..., Client-n是同時(shí)發(fā)送請(qǐng)求到Web服務(wù)器的客戶端應(yīng)用

Web服務(wù)器內(nèi)部維護(hù)著一個(gè)有限的線程池,線程池中線程數(shù)量為m個(gè)

Web服務(wù)器逐個(gè)接收這些請(qǐng)求:

Web服務(wù)器拾取Client-1的請(qǐng)求Request-1,從線程池中拾取一個(gè)線程T-1并將此請(qǐng)求分配給線程T-1

線程T-1讀取Client-1的請(qǐng)求Request-1, 并處理該請(qǐng)求

該請(qǐng)求無阻塞IO處理

處理完必要的步驟后準(zhǔn)備將Response-1發(fā)送回客戶端

Web服務(wù)器又將此Response-1發(fā)送到Client-1

Web服務(wù)器拾取Client-2的請(qǐng)求Request-2,從線程池中拾取一個(gè)線程T-2并將此請(qǐng)求分配給線程T-2

線程T-2讀取Client-2的請(qǐng)求Request-2, 并處理該請(qǐng)求

該請(qǐng)求無阻塞IO處理

處理完必要的步驟后準(zhǔn)備將Response-2發(fā)送回客戶端

Web服務(wù)器又將此Response-2發(fā)送到Client-2

Web服務(wù)器拾取Client-n的請(qǐng)求Request-n,從線程池中拾取一個(gè)線程T-n并將此請(qǐng)求分配給線程T-n

線程T-n讀取Client-n的請(qǐng)求Request-n, 并處理該請(qǐng)求

Request-n需要大量的阻塞IO和計(jì)算操作

線程T-n需要更多時(shí)間與外部系統(tǒng)(SQL, File System)交互,執(zhí)行必要步驟并準(zhǔn)備Response-n并將其發(fā)送回服務(wù)器

Web服務(wù)器又將此Response-n發(fā)送到Client-n

如果"n"大于"m"(大多數(shù)時(shí)候,它是真的),則在使用完所有的m個(gè)線程之后,剩余的客戶端請(qǐng)求會(huì)在隊(duì)列中等待。

如果這些線程中有大量的阻塞IO操作(例如:和數(shù)據(jù)庫、文件系統(tǒng)、外部服務(wù)等交互),那么剩余的客戶端也會(huì)等待更長的時(shí)間。

一旦線程池中的線程空閑且可用于下一個(gè)任務(wù),服務(wù)器就會(huì)拾取這些線程并將它們分配給剩余的客戶端請(qǐng)求。

每個(gè)線程都會(huì)使用到許多資源,如內(nèi)存等。因此,在將這些線程從忙狀態(tài)轉(zhuǎn)到等待狀態(tài)之前,它們應(yīng)該釋放所有獲取的資源。

請(qǐng)求/響應(yīng)無狀態(tài)模型的缺點(diǎn):

在處理越來越多的并發(fā)客戶端請(qǐng)求時(shí)會(huì)變得棘手

當(dāng)客戶端請(qǐng)求增加時(shí),線程也會(huì)越來越多,最后它們會(huì)占用更多內(nèi)存。

客戶端可能需要等待服務(wù)器釋放可用的線程去處理其請(qǐng)求

處理阻塞式的IO任務(wù)時(shí)浪費(fèi)時(shí)間

NodeJS的架構(gòu) - 單線程事件循環(huán)

NodeJS不遵循請(qǐng)求/響應(yīng)多線程無狀態(tài)模型。 它采用單線程與事件循環(huán)模型。 NodeJS的處理模型主要基于Javascript基于事件的模型和Javascript回調(diào)機(jī)制。

因?yàn)镹odeJS遵循的架構(gòu),它可以非常輕松地處理越來越多的并發(fā)客戶端請(qǐng)求。 在討論這個(gè)模型內(nèi)部之前,首先要看下面的圖表。

我試圖設(shè)計(jì)這個(gè)圖來解釋NodeJS內(nèi)部的每一點(diǎn)。

NodeJS的處理模型主要核心是“事件循環(huán)(Event Loop)”。如果我們理解這一點(diǎn),那么很容易理解NodeJS的內(nèi)部架構(gòu)的。

單線程事件循環(huán)模型的處理步驟

客戶端發(fā)送請(qǐng)求到Web服務(wù)器

NodeJS的Web服務(wù)器在內(nèi)部維護(hù)一個(gè)有限的線程池,以便為客戶端請(qǐng)求提供服務(wù)

NodeJS的Web服務(wù)器接收這些請(qǐng)求并將它們放入隊(duì)列中。 它被稱為“事件隊(duì)列”

NodeJS的Web服務(wù)器內(nèi)部有一個(gè)組件,稱為“事件循環(huán)”,它使用無限循環(huán)來接收請(qǐng)求并處理它們。

事件循環(huán)只使用到了一個(gè)線程,它是NodeJS的處理模型的核心

事件循環(huán)回去檢查是否有客戶端的請(qǐng)求被放置在事件隊(duì)列中。如果沒有,會(huì)一直等待事件隊(duì)列中存在請(qǐng)求。

如果有,則會(huì)從事件隊(duì)列中拾取一個(gè)客戶端請(qǐng)求:

開始處理客戶端請(qǐng)求

如果該客戶端請(qǐng)求不需要任何阻塞IO操作,則處理所有內(nèi)容,準(zhǔn)備響應(yīng)并將其發(fā)送回客戶端

如果該客戶端請(qǐng)求需要一些阻塞IO操作,例如與數(shù)據(jù)庫,文件系統(tǒng),外部服務(wù)交互,那么它將遵循不同的方法:

從內(nèi)部線程池檢查線程可用性

獲取一個(gè)線程并將此客戶端請(qǐng)求分配給該線程

該線程負(fù)責(zé)接收該請(qǐng)求,處理該請(qǐng)求,執(zhí)行阻塞IO操作,準(zhǔn)備響應(yīng)并將其發(fā)送回事件循環(huán)

事件循環(huán)依次將響應(yīng)發(fā)送到相應(yīng)的客戶端

圖表說明:

Client-1, Client-2, ..., Client-n是同時(shí)發(fā)送請(qǐng)求到Web服務(wù)器的客戶端應(yīng)用

Web服務(wù)器內(nèi)部維護(hù)著一個(gè)有限的線程池,線程池中線程數(shù)量為m個(gè)

NodeJS的Web服務(wù)器接收到Client-1, Client-2, ..., Client-n的請(qǐng)求后,將請(qǐng)求放入到事件隊(duì)列中

NodeJS的事件循環(huán)從隊(duì)列中開始拾取這些請(qǐng)求:

事件循環(huán)拾取Client-1的請(qǐng)求Request-1

檢查Client-1 Request-1是否確實(shí)需要任何阻塞IO操作,或者需要更多時(shí)間來執(zhí)行復(fù)雜的計(jì)算任務(wù)

由于此請(qǐng)求是簡單計(jì)算和非阻塞IO任務(wù),因此不需要多帶帶的線程來處理它

事件循環(huán)處理該請(qǐng)求所需要的操作,準(zhǔn)備其響應(yīng)Response-1

事件循環(huán)發(fā)送Response-1到Client-1

事件循環(huán)拾取Client-2的請(qǐng)求Request-2

檢查Client-2 Request-2是否需要任何阻塞IO操作或花費(fèi)更多時(shí)間來執(zhí)行復(fù)雜的計(jì)算任務(wù)

由于此請(qǐng)求是簡單計(jì)算和非阻塞IO任務(wù),因此不需要多帶帶的線程來處理它

事件循環(huán)處理該請(qǐng)求所需要的操作,準(zhǔn)備其響應(yīng)Response-2

事件循環(huán)發(fā)送Response-2到Client-2

事件循環(huán)拾取Client-n的請(qǐng)求Request-n

檢查Client-n Request-n是否需要任何阻塞IO操作或花費(fèi)更多時(shí)間來執(zhí)行復(fù)雜的計(jì)算任務(wù)

由于此請(qǐng)求有非常復(fù)雜的計(jì)算或阻塞IO任務(wù),因此事件循環(huán)不會(huì)處理此請(qǐng)求

事件循環(huán)從內(nèi)部線程池中獲取線程T-1,并將此Client-n Request-n分配給線程T-1

線程T-1讀取并處理Request-n,執(zhí)行必要的阻塞IO或計(jì)算任務(wù),最后準(zhǔn)備響應(yīng)Response-n

線程T-1將此Response-n發(fā)送到事件循環(huán)

事件循環(huán)依次將此Response-n發(fā)送到Client-n

此處客戶端請(qǐng)求是對(duì)一個(gè)或多個(gè)JavaScript函數(shù)的調(diào)用,因?yàn)镴avaScript函數(shù)可以調(diào)用其他函數(shù)或可以利用其回調(diào)函數(shù)性質(zhì)。

此所以每個(gè)客戶端的請(qǐng)求處理都看起來向這樣:

例如:

function1(function2,callback1);
function2(function3,callback2);
function3(input-params);

NodeJS的單線程事件循環(huán)的優(yōu)勢

處理越來越多的并發(fā)客戶端請(qǐng)求非常容易

因?yàn)槭录h(huán)的存在,即使我們的NodeJS應(yīng)用接收到了越來越多的并發(fā)請(qǐng)求,我們也不需要去新建很多的線程

NodeJS使用到了較少的線程,所以資源和內(nèi)存的使用較少

原文地址: NodeJS Architecture – Single Threaded Event Loop

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/100107.html

相關(guān)文章

  • JavaScript線程事件循環(huán)(Event Loop)那些事

    摘要:概述本篇主要介紹的運(yùn)行機(jī)制單線程事件循環(huán)結(jié)論先在中利用運(yùn)行至完成和非阻塞完成單線程下異步任務(wù)的處理就是先處理主模塊主線程上的同步任務(wù)再處理異步任務(wù)異步任務(wù)使用事件循環(huán)機(jī)制完成調(diào)度涉及的內(nèi)容有單線程事件循環(huán)同步執(zhí)行異步執(zhí)行定時(shí)器的事件循環(huán)開始 1.概述 本篇主要介紹JavaScript的運(yùn)行機(jī)制:單線程事件循環(huán)(Event Loop). 結(jié)論先: 在JavaScript中, 利用運(yùn)行至...

    Shisui 評(píng)論0 收藏0
  • Nodejs高性能原理(上) --- 異步非阻塞事件驅(qū)動(dòng)模型

    摘要:使用了一個(gè)事件驅(qū)動(dòng)非阻塞式的模型,使其輕量又高效。的包管理器,是全球最大的開源庫生態(tài)系統(tǒng)。按照這個(gè)定義,之前所述的阻塞,非阻塞,多路復(fù)用信號(hào)驅(qū)動(dòng)都屬于同步。 系列文章 Nodejs高性能原理(上) --- 異步非阻塞事件驅(qū)動(dòng)模型Nodejs高性能原理(下) --- 事件循環(huán)詳解 前言 終于開始我nodejs的博客生涯了,先從基本的原理講起.以前寫過一篇瀏覽器執(zhí)行機(jī)制的文章,和nodej...

    yy736044583 評(píng)論0 收藏0
  • JS與Node.js中的事件循環(huán)

    摘要:的單線程,與它的用途有關(guān)。特點(diǎn)的顯著特點(diǎn)異步機(jī)制事件驅(qū)動(dòng)。隊(duì)列的讀取輪詢線程,事件的消費(fèi)者,的主角。它將不同的任務(wù)分配給不同的線程,形成一個(gè)事件循環(huán),以異步的方式將任務(wù)的執(zhí)行結(jié)果返回給引擎。 這兩天跟同事同事討論遇到的一個(gè)問題,js中的event loop,引出了chrome與node中運(yùn)行具有setTimeout和Promise的程序時(shí)候執(zhí)行結(jié)果不一樣的問題,從而引出了Nodejs的...

    abson 評(píng)論0 收藏0
  • nodejs 異步I/O和事件驅(qū)動(dòng)

    摘要:異步和事件驅(qū)動(dòng)注本文是對(duì)眾多博客的學(xué)習(xí)和總結(jié),可能存在理解錯(cuò)誤。接觸有兩個(gè)月,對(duì)的兩大特性一直有點(diǎn)模糊,即異步和事件驅(qū)動(dòng)。 nodejs 異步I/O和事件驅(qū)動(dòng) 注:本文是對(duì)眾多博客的學(xué)習(xí)和總結(jié),可能存在理解錯(cuò)誤。請(qǐng)帶著懷疑的眼光,同時(shí)如果有錯(cuò)誤希望能指出。 接觸nodejs有兩個(gè)月,對(duì)nodejs的兩大特性一直有點(diǎn)模糊,即異步IO和事件驅(qū)動(dòng)。通過對(duì)《深入淺出nodejs》和幾篇博客的閱...

    binaryTree 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<