剛開始了解Node感覺很吊,各種說高性能,可是一直不理解為什么單線程會比多線程快?為什么異步IO比非阻塞IO快?因此,本篇在閱讀相關書籍后,根據自己的理解,整理此文,如有錯誤,僅代表理論不精,必當修改,以免誤導他人。還請多多指正.....
關於阻塞IO和非阻塞IO
系統內核只有兩種IO模式—— 阻塞IO和非阻塞IO。這里的IO可不僅僅是讀取文件內容,而是更為廣泛的概念。比如Socket啊,網絡Socket,磁盤讀取等等,這些相比於CPU計算都是很耗時的。
下圖為阻塞IO的工作模式:
阻塞IO在需要獲取數據進行IO操作時,CPU會等待,當讀取完成后,再繼續運行。那么很容易就能想到,如果讀取很耗時,CPU就會長期處於阻塞狀態,顯然效率很低。
再看看非阻塞IO:
非阻塞IO在進行IO操作時,會直接返回。然后CPU該干嘛干嘛,只不過需要一定的策略來確定什么時間請求數據完成,這個時候就需要一些輪訓策略了,比如select poll等等。那么這個也應該能想到,當有長期的IO操作,會白白執行大量的查詢操作,效率也不高。(當然目前的系統內的非阻塞IO都是很高級的玩法,鹵煮也沒有仔細研究,就不獻丑了)
異步IO與Node工作原理
通過上面兩種典型的IO操作,很顯然,一種理想的模型是,有IO操作時,系統去執行IO操作,CPU該干嘛干嘛,當請求數據完成后,就通知CPU繼續執行剛才沒有完成的工作。
Node就是利用了javascript的回調函數思想,實現這種工作模式。
那么為什么單線程的Node會效率很高呢?什么又是事件機制呢?
原來,一直說的單線程,都是javascript端的,Node底層還是使用c來實現,因此底層仍然是多線程的。只不過,Node基於不同的操作系統linux或者windows之上實現了一個封裝層,用戶執行的操作命令會轉交給這個封裝層,由它再去判斷操作系統,進而調用相應平台的c代碼。
有點跑題了,簡單的說,就是Node只是表面暴露給用戶的javascript代碼是單線程的,底層還是多線程的。
說到事件機制,就要上圖了!
簡單的解釋一下,當我們使用Node的時候,會在javascript觸發一些命令調用方法,這些方法會被包裝成一個對象,放入線程池,然后前面的方法就返回了,繼續執行下面的JS代碼。
線程池中采用多線程的方式執行,執行完的對象放入事件循環隊列。
事件循環隊列采用類似while(true)這種循環的方式,不斷的查看是否有事件,並且讀取是否包含回調,由於前面回調函數被包裝到對象中,這里直接調用執行就可以了。
通過這三種階段,就實現了 【 異步請求——>回調 】 的工作模式。