nodejs是近年來比較火的服務端js平台,這一方面得益於其在後端處理高併發的卓越效能,另一方面在nodejs平台上的npm、grunt、express等強大的**與專案管理應用崛起,幾乎重新定義了前端的工作方式和流程。
nodejs的成功標誌著它的強大,但是不是所有情況都適合應用nodejs作為伺服器端平台呢?
答案當然是否定的,而網上也是眾說紛紜。那我們從原理出發了解一下nodejs的適用情況。
在講nodejs之前我們不仿先看一下傳統(以apache為代表)
的伺服器端處理平台處理併發的方式。
1. apache的多執行緒高併發模式
那有的同學會奇怪,apache不是多執行緒處理併發嗎,為什麼還會出現阻塞呢?
要明白這一點我們首先需要了解執行緒這個概念
1.1 什麼是執行緒?
(注意這個特點)。
我們可以看到同乙個程序下的執行緒是會共享相同的檔案和記憶體的(記憶體位址空間),所以大家可以想象,當不同的執行緒需要占用同乙個變數時,根據先到先得的原則,先到的執行緒在運作時,後來的執行緒只能在旁邊等待,也就是加入到了阻塞排隊序列。所以這就是造成執行緒阻塞的原因。
因此,雖說程序可以支援多個執行緒,它們看似同時執行,但互相之間並不同步。乙個程序中的多個執行緒共享相同的記憶體位址空間,這就意味著它們可以訪問相同的變數和物件,而且它們從同一堆中分配物件。儘管這讓執行緒之間共享資訊變得更容易,因為程式設計者必須小心,確保它們不會妨礙同一程序裡的其它執行緒。
了解了多執行緒並行的缺陷後,我們就可以更好地理解nodejs的強大所在了。因為nodejs是非同步單執行緒的!
2. nodejs的非同步i/o原理
我們先來看一段apache請求資料庫的**:
**執行到第一行的時候執行緒會阻塞,等待query返回結果,然後繼續處理。由於資料庫查詢、磁碟讀寫、網路通訊等原因(所謂的i/o)阻塞時間會非常大(相對於cpu始終頻率)。對於高併發的訪問,一方面執行緒長期阻塞等待,另一方面為了應付新情求而不斷新增新執行緒,會浪費大量系統資源,同時執行緒的增加也會也會占用大量的cpu時間來處理記憶體上下文切換。看看node.js怎麼處理。
看到沒,就四個字:非同步**。query的第二個引數是乙個**函式,程序執行到db.query的時候不會等待結果返回,而是直接繼續執行下面的語句,直到進入事件迴圈。當資料庫執行結果返回的時候會將事件傳送到事件佇列,等到執行緒進入事件迴圈後才會呼叫之前的**函式。更專業的說法是非同步i/o。只要單執行緒就可以。
那為什麼nodejs做到單執行緒,卻可以實現非同步呢?在這裡我們先上一幅圖,直戳圖中的event queue
看到沒,nodejs的工作原理其實就是事件迴圈。可以說每一條nodejs的邏輯都是寫在**函式裡面的,而**函式都是有返回之後才非同步執行的!
看到這裡,你不禁會驚嘆,nodejs如果所有處理都非同步,豈不是曉得飛了?錯錯錯!當然不是,不要忘記,nodejs實現這些的基礎是單執行緒。沒錯,單執行緒!一條執行緒扛起所有操作!
你可以想象一下,nodejs在寒風中面對著10萬併發大軍,ok,沒問題,上來敵人乙個扔到城裡,上來乙個又扔到城裡。城裡全民皆兵,可以很好地消化這些敵人。但如果上來乙個類似於張飛趙雲這樣的人物,老node心裡一慘,和張飛大戰300回合,把他打殘了,再扔到城裡。那後面的10萬大軍就得等這300回合。。。
所以這說明什麼?說明nodejs不是沒有阻塞,而是阻塞不發生在後續**的流程,而會發生在nodejs本身對邏輯的計算和處理。我們已經知道,nodejs的分發能力無比強大,可以迴圈事件進行非同步**。但如果在迴圈事件時遇到複雜的邏輯運算,那麼單薄的單執行緒怎麼支撐得起上百萬的邏輯+
併發呢?
nodejs它的所有i/o、網路通訊等比較耗時的操作,都可以交給worker threads執行再**,所以很快。但cpu的正常操作,它就只能自己抗了。
說到這裡,各位對nodejs的特性估計也大概有個譜了。所以說適用的場景基本是呼之欲出了~!
3. nodejs的應用場景
順便提一下apache,打壓了這麼多,給顆甜棗。apache由於其多執行緒高併發共享記憶體位址空間的特性,那就意味著如果伺服器足夠強大,處理器足夠高核,apache的運作將會非常良好,所以適用於(併發)非同步處理相對較少,後台計算量大,後台業務邏輯複雜的應用程式。
JO JNO JB JNB命令詳解(從原理上)
當執行到jo命令時,如果zf標誌位為1,則跳轉,反之不跳轉 add eax,ecx jo 00401000c此時eax 7fff ffff ecx 0000 0001,執行完add命令,of 1,原因是eax儲存的最大值是7fffffff,再加1,會溢位,當執行jo時跳轉 當執行到jno命令時,如果...
程式設計基礎 從原理上理解和計算取餘和取模
計算原理 總結分析 參考取餘和取模都是用來計算餘數,但由於實現原理不同,結果可能不同 被除數和除數異號時結果不同 取餘和取模的表達 取整函式fix和floor rem x,y 用到fix。floor函式 mod x,y 用到floor。總結 取餘運算 舉例 rem 5,2 1 rem 5,2 1 r...
從原理上搞定編碼 Base64編碼
一.base64編碼由來 為什麼會有base64編碼呢?因為有些網路傳送渠道並不支援所有的位元組,例如傳統的郵件只支援可見字元的傳送,像ascii碼的控制字元就 不能通過郵件傳送。這樣用途就受到了很大的限制,比如二進位製流的每個位元組不可能全部是可見字元,所以就傳送不了。最好的方法就是在不改變傳統協...