2016-01-23 79 views
1

在過去的日子裏,我一直在研究如何理解Node.js基於事件的風格如何處理比傳統的多線程方法更多的併發請求。最後,所有關於內存佔用和內存切換的內容都減少了,因爲Node.js只使用了幾個線程(V8單線程和一堆C++工作線程以及libuv的主線程)。在Node.js中扮演V8引擎的角色是什麼?

但是如何處理大量帶有幾個線程的請求,因爲最後一些線程必須被阻塞等待,例如數據庫讀取操作。 我認爲這個想法是:而不是同時阻塞客戶端線程和數據庫線程,只有數據庫線程被阻塞,並在客戶端線程結束時提醒客戶端線程。

這就是我理解Node.js的工作原理。

我一直在想,是什麼賦予Node.js處理HTTP請求的能力。 根據我閱讀到現在爲止,我的理解是libuv是誰做的工作:

把手代表能夠積極而執行某些操作 長壽命的對象。一些示例:當處於活動狀態時,準備句柄的每個循環迭代都會調用一次 回調,並且a TCP 服務器句柄在每次有新連接時都會調用它的連接回調。

enter image description here

所以,這是等待進入的HTTP請求的線程是libuv的主線程執行所述libuv事件循環。

所以,當我們在寫

const http = require('http'); 

const hostname = '127.0.0.1'; 
const port = 1337; 

http.createServer((req, res) => { 
    res.writeHead(200, { 'Content-Type': 'text/plain' }); 
    res.end('Hello World\n'); 
}).listen(port, hostname,() => { 
    console.log(`Server running at http://${hostname}:${port}/`); 
}); 

...我在libuv投入,將在V8引擎,當請求中執行的回調?

的事件的順序將然後是

  1. 一個TCP數據包到達
  2. 操作系統創建一個事件,併發送至事件循環
  3. 事件循環處理該事件並創建一個V8事件

如果我在處理請求的匿名函數中執行阻塞代碼,我將阻塞V8線程。

爲了避免這種情況,我需要執行將在另一個線程中執行的非阻塞代碼。我想這「另一個線程」是libuv的主線程,其中

網絡I/O始終是在單個線程執行,每次循環的線程

這個線程不會阻止,因爲使用OS系統調用是異步的。

的epoll在Linux上,在OSX和其他BSD系統的kqueue,事件端口在SunOS 和IOCP在Windows

我也假設http.request是使用libuv這個achive。

相似,如果我需要做一些文件I/O而不阻塞V8線程
我將使用Node的FileSystem模塊。這次libuv主線程不能以非阻塞的方式處理這個問題,因爲操作系統不提供這個功能。

與網絡I/O,沒有特定於平臺的文件I/O原語 libuv可以依靠,所以目前的辦法是運行阻止文件 I/O操作的線程池。

在這種情況下,爲了不阻止libuv事件循環,需要經典的線程池。

現在,如果我需要查詢數據庫,所有不阻止V8線程和libuv線程的責任都在驅動程序開發人員的手中。 如果驅動程序不使用libuv,它將阻止V8引擎。

相反,如果它使用libuv但基礎數據庫不具有異步功能,那麼它將block a worker thread

最後,如果數據庫提供異步功能,它只會阻塞數據庫線程。 (在這種情況下,我可以根本避免libuv並直接從V8線程調用驅動程序)

如果這個結論正確描述,儘管以簡單的方式說明了libuv和V8在Node.js中一起工作的方式,我無法看到使用V8的好處,因爲我們可以直接在libuv中完成所有工作(除非目標是爲開發人員提供一種允許以更簡單的方式編寫基於事件的代碼的語言)。

回答

0

從我所知道的差異主要是異步I/O。在傳統的每請求處理或每請求線程服務器中,I/O(最顯着的是網絡I/O)傳統上是同步I/O。 Node.js使用的線程少於Apache或其他,並且它可以處理流量,主要是因爲它使用異步網絡I/O。

Node.js需要V8來實際解釋JS代碼並將其轉換爲機器代碼。 Libuv需要做真正的I/O。我不知道更多:)

0

有一個很好的帖子關於node.js V8引擎:How JavaScript works: inside the V8 engine + 5 tips on how to write optimized code。它解釋了引擎的許多深入細節和使用它的一些重要建議。

簡而言之,V8 engine(和其他javascript engines)所做的就是執行javascript代碼。然而,與其他人相比,V8 engine獲得了高性能執行。

V8將JavaScript代碼翻譯成更高效的機器代碼,而不是使用解釋器的 。它通過實現JIT(Just-In-Time)編譯器將JavaScript代碼編譯成機器代碼 ......

0

I/O通過libuv進行非阻塞和異步操作,其中底層使用像epoll或類似的OS原語,具體取決於平臺,以使I/O無阻塞。當fd上的事件(例如tcp套接字)發生時,Nodejs事件循環獲得排隊的事件

相關問題