簡體   English   中英

Node.js中的單線程和事件循環

[英]Single threaded and Event Loop in Node.js

首先,我是嘗試了解什么是Node.Js. 我有兩個問題。

第一個問題
從Felix 的文章中,它說“在同一時間只能有一個回調觸發。在回調完成執行之前,所有其他回調都必須排隊”。

然后,考慮以下代碼(從nodejs官方網站復制)

var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8124, "127.0.0.1");

如果同時收到兩個客戶端請求,則表示以下工作流程:

  1. 收到第一個http請求事件,收到第二個請求事件。
  2. 收到第一個事件后,第一個事件的回調函數正在執行。
  3. 同時,第二個事件的回調函數必須等待。

我對嗎? 如果我是對的,如果在非常短的時間內有數千個客戶端請求, Node.js如何控制。

第二個問題
術語“事件循環”主要用於Node.js主題。 我從http://www.wisegeek.com/what-is-an-event-loop.htm了解到“事件循環”如下

事件循環 - 或主循環,是程序中的一個構造,用於控制和分派初始事件后的事件。

初始事件可以是任何東西,包括按下鍵盤上的按鈕或單擊程序上的按鈕(在Node.js中,我認為初始事件將是http請求,數據庫查詢或I / O文件訪問)。

這稱為循環,不是因為事件循環並且連續發生,而是因為循環准備事件,檢查事件,調度事件並重新重復該過程。

我對第二段有沖突,特別是“ 重復這個過程 ”這句話。 我接受上面的問題上面的http.createServer代碼絕對是“事件循環”,因為它反復監聽http請求事件。

但我不知道如何識別以下代碼,無論是事件驅動還是事件循環。 除了在db查詢完成后觸發的回調函數之外,它不會重復任何操作。

database.query("SELECT * FROM table", function(rows) {
  var result = rows;
});

請讓我聽聽你的意見和答案。

回答一 ,你的邏輯是正確的:第二個事件將等待。 並且將執行其排隊的回調時間到來。

同樣,請記住技術世界中沒有“同時”這樣的東西。 一切都有非常具體的地點和時間。

node.js管理數千個連接的方式是,在有一些數據庫調用阻塞邏輯或者正在處理另一個IO操作(例如流)時,不需要保持線程空閑。 它可以“提供”第一個請求,可能會創建更多回調,然后繼續進行其他操作。
因為沒有辦法阻止執行(除了廢話(真實)和類似),它在整個應用程序邏輯中傳播實際資源變得非常有效。

線程 - 價格昂貴,線程的服務器容量與可用內存直接相關。 因此,大多數經典Web應用程序都會受到影響,因為在數據庫查詢塊正在進行或類似的情況下,RAM用於簡單空閑的線程。 在節點中不是一個案例。

它仍然允許通過cluster創建多個線程(作為child_process),這擴展了更多的可能性。

答案二 沒有你想到的“循環”這樣的東西。 幕后沒有循環可以檢查是否有連接或接收到任何數據等等。 現在它也由Async方法處理。

因此從應用程序的角度來看,沒有“主循環”,從開發人員的角度來看,一切都是事件驅動的(不是事件循環)。

對於http.createServer ,您將回調綁定為對請求的響應。 所有套接字操作和IO內容都將在幕后發生,以及HTTP握手,解析標頭,查詢,參數等。 一旦它在幕后發生並且工作完成,它將保留數據並將回調推送到具有一些數據的事件循環。 一旦事件循環生效並且將到來它將在node.js應用程序上下文中執行您的回調與來自幕后的數據。

隨着數據庫請求 - 同樣的故事。 它不准備並詢問內容(可能會再次執行異步),然后在數據庫響應並將為應用程序上下文准備數據時進行回調。

說實話,node.js所需要的只是理解概念,而不是事件的實現。 最好的方法 - 實驗。

1)是的,你是對的。

它的工作原理是因為您對節點所做的一切主要是I / O綁定。

當一個新的請求(事件)進入時,它被放入隊列中。 在初始化時,Node分配一個ThreadPool,負責為I / O綁定處理產生線程,如網絡/套接字調用,數據庫等(這是非阻塞的)。

現在,你的“回調”(或事件處理程序)非常快,因為你正在做的大多數事情很可能是CRUD和I / O操作,而不是CPU密集型。

因此,這些回調讓人感覺它們是並行處理的,但它們實際上並非如此,因為實際的並行工作是通過ThreadPool(具有多線程)完成的,而回調本身只是接收結果從這些線程,以便處理可以繼續並將響應發送回客戶端。

您可以輕松驗證這一點:如果您的回調是繁重的 CPU任務,您可以確保每秒處理數千個請求,並且與多線程系統相比,它可以非常糟糕地縮小。

2)你是對的。

不幸的是,由於所有這些抽象,你必須潛水,以了解背景中發生了什么。 但是,是的,有一個循環。

特別是,Nodejs是用libuv實現的。

有趣的閱讀

但我不知道如何識別以下代碼,無論是事件驅動還是事件循環。 除了在db查詢完成后觸發的回調函數之外,它不會重復任何操作。

事件驅動是您通常在存在事件循環時使用的術語,它表示由諸如點擊按鈕,數據到達等事件驅動的應用程序。通常,您將回調與此類事件相關聯。

暫無
暫無

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

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