2014-11-04 21 views
0

我知道這個問題已經在過去詳細討論過了(How is Node.js inherently faster when it still relies on Threads internally?),但我仍然無法正確理解node.js事件循環模型並且是單線程模型,它如何處理併發請求。Node.js事件循環模型如何擴展很好

Uptil現在我的理解是:我們收到一個IO請求 - >一個線程由node.js在內部產生,IO請求交給它 - >因爲這是一個IO請求,所以CPU把它交給DMA控制器並釋放此線程 - >此線程再次進入線程池以提供不同的請求 - > DMA仍在執行IO,一旦DMA獲取所有數據,某種事件被觸發 - >此事件被捕獲node.js系統,它將提供的回調函數放在事件循環中 - >當事件循環有機會執行對IO提取的數據的回調時 - >由於閉包,回調函數對獲取的數據執行通過回調只有

所以這個過程不斷重複。請人闡明我的理解,並提供一些信息

+0

好吧,你清楚地瞭解eventloop是如何工作的,我不知道我們可以說這會讓它*點擊*給你。當諸如數據庫交互,文件訪問等事件發生時,事件循環繼續,處理其他請求,同時等待所述事件完成。這些其他事件由系統在單獨的線程中發生,而不是由節點發生。 – 2014-11-04 17:11:30

+0

也許這裏的答案會有所幫助? http://stackoverflow.com/questions/22887216/how-does-a-single-threaded-event-driven-webserver-like-node-js-work-at-the-soc – 2014-11-04 17:14:05

+0

我相信我的一般理解是清楚的...但我正在尋找更好的細節...當我說「因爲這是一個IO請求,所以CPU把它交給DMA控制器並釋放這個線程 - >這個線程再次進入線程池以提供不同的請求「這是否正確,並且是節點中線程消耗數量較少(因此內存使用量較少)的原因?在另一個像java這樣的系統中,如果我編寫相同的邏輯,即將一個IO請求傳遞給一個線程,那麼該線程是否會等待請求完成? – JackSparrow 2014-11-04 18:10:37

回答

1

只有一個線程(主線程),用於處理網絡I/O(文件I/O是一個稍微不同的故事,因爲不是所有的平臺都提供可用異步,非阻塞文件I/O API,因此在線程池中的這些平臺上使用同步文件I/O API)。

所以當網絡請求進來時,它們全部由主線程使用(間接通過libuv)epoll/kqueue/IOCP /等來處理。用於在數據可用時(或者例如存在傳入的TCP連接)檢測(以非阻塞方式)。如果有數據可用,則根據需要適當調用javascript,傳遞套接字數據。如果套接字上沒有數據(並且事件循環沒有其他內容用於執行,例如,引發定時器),則執行過程繼續到事件循環的下一次迭代,此處重新開始該過程。

只要將套接字數據與套接字javascript對象關聯起來,它就是C++封裝器對象(例如,tcp_wrap,udp_wrap等)和確保數據到達適當位置的JavaScript對象的組合。

這是稍微老一點的圖解釋了節點事件循環的單個循環中會發生什麼。其中一些可能已經因爲節點V0.9略有變化,但它可以讓你的總體思路:

enter image description here

+0

你從哪裏得到這張照片? – Bergi 2015-07-23 09:38:02

+0

@Bergi IRC的一位核心開發人員很早以前就發佈了一個鏈接,在v0.10發佈之前。 – mscdex 2015-07-23 15:38:18

0

的node.js具有消除了對鎖和信號量需要一個單線程模型(使用傳統的多線程模型)。鎖和信號量可以增加性能方面的成本,更重要的是,可以提供大量的繩索來掛斷(換句話說,許多陷阱)。 IO操作並行發生,並且由於IO之間的工作通常非常小,所以這種單線程模型通常工作得非常好。

(邊注:如果你有一個應用程序,做了很多的IO操作,即CPU密集的應用程序之間的工作,那就是節點沒有很好地擴展的情況下)

我這樣想的關於節點模型爲什麼能夠很好地擴展的論點與人們認爲NoSQL比SQL數據庫擴展的原因相同。顯然Java(多線程)和SQL規模;像Facebook和Twitter這樣的大公司已經證明了這一點。但是,就像在SQL中一樣,有很多事情可能會不正確地降低性能。 Node.js並沒有消除所有潛在的問題,它只是很好地限制了許多常見的原因。