簡體   English   中英

Node.js 單線程機制

[英]Node.js single-thread mechanism

我了解到 Node.js 是單線程且非阻塞的。 這里我看到了一個很好的解釋,一般來說,Node.js 如何處理 10,000 個並發請求? 但是第一個答案說

看似神秘的事情是,上述兩種方法是如何“並行”運行工作負載的? 答案是數據庫是線程化的。 所以我們的單線程應用實際上是在利用另一個進程的多線程行為:數據庫。

(1) 這讓我感到困惑。 以一個簡單的快遞應用為例,當我

var monk = require('monk');
var db = monk('localhost:27017/databaseName');

router.get('/QueryVideo', function(req, res) { 
var collection = db.get('videos'); 
collection.find({}, function(err, videos){
    if (err) throw err;  
res.render('index', { videos: videos })
   });
});

當我的路由器通過簡單的 MongoDB 查詢響應多個請求時。 這些查詢是否由不同的線程處理? 我知道節點中只有一個線程可以路由客戶端請求。

(2)我的第二個問題是,這樣的單線程節點應用如何保證安全? 我對安全性了解不多,但看起來應該隔離多個請求(至少不同的 memory 空間?)即使多線程應用程序不能確保安全性,因為它們仍然共享很多東西。 我知道這可能不是一個合理的問題,但在今天的雲服務中,隔離似乎是一個重要的話題。 我迷失在使用 Node.js 環境的無服務器、wasm 和基於 wasm 的無服務器等主題中。

謝謝您的幫助!!

(1) 大局是這樣的; 對於 nodejs,有 2 種類型的線程:事件(單個)和工作線程(池)。 只要你不阻塞事件循環,在 nodejs 將阻塞的 I/O 調用放置到工作線程之后; nodejs 繼續為下一個請求提供服務。 工作人員將完成的 I/O 放回事件循環以進行下一步操作。

簡而言之,主線程:“在需要等待時執行其他操作,等待結束后返回並繼續,並且一次執行此操作”。

而且這種反應機制與運行在另一個進程(即數據庫)中的線程無關。 數據庫可以部署其他類型的線程管理方案。

(2)您問題中的“內存空間”位於同一進程空間中。 一個線程屬於一個進程(即 Express 應用 A)永遠不會在其他進程(即 Fastify 應用 B)空間中運行。

既然你問我的答案,我想我可以幫助澄清一下。

1

對於處理多個並行客戶端請求的特定情況,該請求會觸發您詢問的多個並行 MongoDB 查詢:

這些查詢是否由不同的線程處理?

在 node.js 上,由於 MongoDB 通過網絡堆棧 (tcp/ip) 連接,所有並行請求都在單個線程中處理。 神奇的是系統 API,它允許您的程序並行等待 Node.js 使用libuv到 select 哪個 API 取決於在編譯時使用哪個操作系統。 但是哪個 API 並不重要。 知道所有現代操作系統都有 API 允許您並行等待多個 sockets 就足夠了(而不是通常在多個線程/進程中等待單個套接字)。 這些 API 統稱為異步 I/O API。

關於 MongoDB.. 我對 MongoDB 了解不多。 Mongo 可以在多個線程中實現,也可以像 node.js 那樣是單線程的。 磁盤 I/O 本身由操作系統並行處理,不使用線程,而是使用 I/O 通道(例如PCI 通道)和DMA通道。 基本上,線程/進程和異步 I/O 通常由操作系統(至少在 Linux 和 Mac 上)使用相同的底層系統:操作系統事件來實現。 操作系統事件只是處理中斷的函數。 無論如何,這與關於數據庫的討論相去甚遠。

I know that MySQL and Postgresql are both multithreaded to handle parsing the SQL query loop (query processing in SQL are basically operations that loop through rows and filter the result - this requires both I/O and CPU which is why they're multithreaded)

如果您仍然好奇計算機如何在 CPU 不執行單條指令的情況下執行操作(例如等待 I/O),您可以查看我對以下相關問題的回答:

有沒有其他方法可以在沒有無限while循環的情況下實現“監聽” function ?

允許調度程序切換正在執行的線程的機制是什么?

2

通過被解釋的語言並確保解釋器沒有任何堆棧溢出或下溢錯誤來確保安全性。 在大多數情況下,所有現代 javascript 引擎都是如此。 通過程序輸入注入代碼和執行外部代碼的主要機制是通過緩沖區溢出或下溢。 能夠執行外部代碼然后允許您訪問 memory。 如果您無法執行能夠訪問 memory 的外部代碼,那是沒有實際意義的。

還有第二種注入外來代碼的機制,這在某些編程語言文化中很普遍:代碼評估(我在看你 PHP。)。 無論您的程序的 memory 模型如何,使用字符串替換以任何語言構造數據庫查詢都會使您面臨 sql 代碼評估攻擊(通常稱為 sql 注入)。 Javascript 本身有一個eval() function。 為了防止這種 javascript 程序員簡單地考慮eval evil。 基本上,對eval的保護取決於良好的編程實踐,並且 Node.js 是開源的,允許任何人查看代碼並報告任何可能發生代碼評估攻擊的情況。 從歷史上看,Node.js 在這方面已經相當不錯了——所以你對代碼 eval 安全性的主要保證是 Node 的聲譽。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM