這篇譯章探究了NodeJS的架構和單線程事件循環模型。咱們將在本文中討論「NodeJS如何在底層工做,它遵循什麼類型的處理模型,NodeJS如何使用單線程模型處理併發請求」等內容。node
正如咱們剛纔說的,NodeJS使用的是「單線程事件循環模型」的架構去處理多個併發的客戶端請求的。數據庫
有許多Web應用程序技術,如JSP,Spring MVC,ASP.NET等。但全部這些技術都遵循「多線程請求 - 響應」架構來處理多個併發客戶端。服務器
咱們已經熟悉「多線程請求 - 響應」架構,由於它被大多數Web應用程序框架使用。 可是爲何NodeJS選擇了不一樣的架構來開發Web應用程序。多線程和單線程事件循環體系結構之間的主要區別是什麼?多線程
NodeJS使用「單線程事件循環模型」架構來處理多個併發客戶端。然而它是如何真正處理併發客戶端請求且不使用多個線程。什麼是事件循環模型?咱們將逐一討論這些概念。架構
在討論「單線程事件循環」架構以前,首先咱們將介紹著名的「多線程請求 - 響應」架構。併發
任何非NodeJS開發的Web應用程序一般都遵循「多線程請求 - 響應」模型。咱們能夠將此模型稱爲請求/響應模型。框架
客戶端向服務器發送請求,而後服務器根據客戶端請求進行一些處理,準備響應並將其發送回客戶端。函數
該模型使用HTTP協議。因爲HTTP是無狀態協議,所以該請求/響應模型也是無狀態模型。因此咱們能夠將其稱爲請求/響應無狀態模型。oop
可是,此模型使用多線程來處理併發客戶端請求。 在討論這個模型內部以前,首先要看下面的內容。spa
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