叢集和工作線程 - Node JS
在上一篇文章「Node JS 內部結構」中,我們討論了Node JS 內部架構,並討論了為什麼我們應該增加節點線程池大小以同時處理多個請求。我已經告訴過你,可擴展性和效能與線程池大小無關。
為了可擴展性和高效能,我們可以使用叢集和工作執行緒。
聚類
假設您正在參加一場盛大的婚禮,有數千位賓客參加婚禮。有一間廚房,一名廚師正在為所有這些客人準備食物。聽起來不可預測,對吧?如果您只有一名廚師,您就沒有充分利用廚房的全部資源。
這正是在多核心 CPU 上執行的 Node JS 應用程式中發生的情況,當僅使用一個核心來處理所有請求時。因此,即使我們的機器具有多核心的能力,如果沒有集群,我們的應用程式也只能在單核心上運行。一個核心負責處理所有工作。
當你的廚房裡有多個廚師正在工作時,這就是集群。
叢集是一種讓單一 Node JS 應用程式能夠有效利用多個 CPU 核心的技術。
要實作集群,您必須使用 Node JS 中的集群模組。
const cluster = require('cluster');
透過使用此叢集模組,您可以建立 Node JS 應用程式的多個實例。這些實例稱為工人。所有工作人員共用相同的伺服器連接埠並同時處理傳入請求。
叢集架構中有兩種類型的進程。
1.主流程:
Master進程就像廚房裡的主廚管理工人。它初始化應用程序,設定叢集環境,並將任務委託給工作進程。它不直接處理應用程式請求。
Master進程是做什麼的?
使用 cluster.fork() 方法建立多個工作進程。如果工作人員意外崩潰或退出,它也會重新啟動工作人員。
它確保傳入請求分佈在所有工作流程中。在 Linux 上,這是由作業系統處理的,在 Windows 上,Node JS 本身充當負載平衡器。
它可以透過IPC(進程間通訊)在worker之間進行通訊。
2.工作進程:
工作進程是主進程所建立的 Node JS 應用程式的實例。每個進程在單獨的 CPU 核心上獨立運行並處理傳入請求。
工作進程無法直接相互通信,它們透過主進程進行通訊。
工作進程處理傳入的請求並執行一些任務,例如資料庫查詢、計算或任何應用程式邏輯。
const cluster = require('cluster');
在這裡,我們先檢查這是主進程。如果是,那麼它將創建工作進程。
在我們的程式碼中,我使用 cluster.fork() 建立一個工作進程。
但是,這不是創建工作進程的理想方式。
假設您正在建立 4 個工作進程,而您的系統有兩個核心。
為了解決這個問題,而不是創建硬編碼的工作進程,先找到 CPU 核心,然後考慮資料創建工作進程。
const cluster = require('cluster'); const os = require('os'); if (cluster.isMaster) { console.log(`Master ${process.pid} is running`); // Fork workers cluster.fork(); cluster.fork(); cluster.fork(); cluster.fork(); } else { console.log(`Worker ${process.pid} is running`); // Worker logic (e.g., server setup) goes here }
我使用雙核心系統,所以輸出將如下所示。
const cluster = require('cluster'); const os = require('os'); if (cluster.isMaster) { console.log(`Master ${process.pid} is running`); const numCPUs = os.cpus().length; // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork(); } } else { console.log(`Worker ${process.pid} is running`); // Worker logic (e.g., server setup) goes here }
現在,您有一個問題,如果您有雙核心 CPU,那麼為什麼要建立 4 個工作進程?
這是因為邏輯核心數為 4,我的 CPU 支援超執行緒或同步多執行緒 (SMT)。
工作執行緒
在餐廳裡,服務生接受訂單並將訂單交給廚師團隊,因為烹飪需要一些時間。如果有清潔桌子或任何其他與服務員相關的工作,那麼服務員就會這樣做。當訂單準備好後,廚師將食物回饋給服務員,服務員將這些食物提供給顧客。
這與工作執行緒相關的場景相同。如果出現任何計算量大的任務,例如大規模資料處理、複雜計算或繁重演算法,則主執行緒會將此任務委託給工作執行緒。該任務由工作執行緒執行,而不是主執行緒。
*為什麼,這有幫助? *
我們知道 Node JS 事件循環是單執行緒的,如果這種繁重的運算工作由主執行緒完成,那麼事件循環將被阻塞。如果您使用這些工作線程,那麼這些繁重的任務將交給工作線程,工作線程執行這些任務,而不是主線程,因此事件循環不會被阻塞。
工作執行緒可以透過訊息傳遞系統與主執行緒通信,並且可以使用結構化克隆(深複製)在執行緒之間發送資料。
現在,我們正在嘗試模仿工作執行緒的工作。
main.js(主執行緒)
Master 12345 is running Worker 12346 is running Worker 12347 is running Worker 12348 is running Worker 12349 is running
worker.js(工作執行緒)
const { Worker } = require('worker_threads'); function startWorker() { const worker = new Worker('./worker.js'); // Create a worker using worker.js // Listen for messages from the worker worker.on('message', (message) => { console.log('Message from worker:', message); }); // Handle errors in the worker worker.on('error', (error) => { console.error('Worker error:', error); }); // Handle worker exit worker.on('exit', (code) => { console.log(`Worker exited with code ${code}`); }); // Send a message to the worker worker.postMessage({ num: 100 }); } startWorker();
如果資料包含大型結構,它將被深度克隆並傳遞,這可能會產生一些效能開銷。
程式碼的工作
Worker 類別用於產生新執行緒。
您可以使用worker.postMessage向worker發送數據,並使用worker.on('message',callback)監聽訊息。
在工作執行緒中,parentPort 是與主執行緒通訊的主要介面。
您可以監聽來自主執行緒(parentPort.on('message'))的訊息並使用parentPort.postMessage傳回訊息。
輸出將是:
const cluster = require('cluster');
現在,您還有一個問題:為什麼我們不建立數百個工作執行緒?
但是,原因是如果您建立的執行緒多於核心數量,執行緒將競爭 CPU 時間,導致上下文切換,這會導致成本高昂並降低整體效能。
什麼時候應該在 Node.js 中使用叢集、工作執行緒或兩者?
1。何時使用工作執行緒?
- CPU 密集任務:
涉及大量計算的任務,例如影像/視訊處理、資料壓縮或加密、機器學習推理、科學計算
- 需要共享記憶體:
您需要在執行緒之間有效地共享資料而不重複資料。
- 單核心使用:
如果您的應用程式只需要在單一進程內擴展,但仍需要 CPU 密集型任務的並行性。
2.什麼時候使用聚類?
- I/O 限制:
任務涉及處理大量客戶端請求,例如 Web、伺服器、聊天應用程式和 API。叢集透過在所有 CPU 核心之間分配請求來幫助水平擴展。
- 孤立的記憶:
您的應用程式不需要在進程之間共享大量資料。
- 多核心利用率:
您希望透過產生多個 Node.js 進程來利用所有可用的核心。
3.什麼時候同時使用叢集和工作執行緒?
- I/O 密集型 CPU 密集型任務:
應用程式處理 HTTP 請求,但卸載計算密集型任務。範例:網頁伺服器處理檔案上傳並執行影像大小調整或影片轉碼。
- 高擴充性:
您需要進程級和執行緒級並行性才能實現高吞吐量。在電子商務網站中,叢集可確保多個進程處理傳入要求。工作執行緒處理後台任務,例如產生個人化推薦。
謝謝。
歡迎提出問題或提出任何建議。
如果您發現本文內容豐富,請按讚。
以上是叢集和工作線程 - Node JS的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript不需要安裝,因為它已內置於現代瀏覽器中。你只需文本編輯器和瀏覽器即可開始使用。 1)在瀏覽器環境中,通過標籤嵌入HTML文件中運行。 2)在Node.js環境中,下載並安裝Node.js後,通過命令行運行JavaScript文件。
