一般狀況下 Node.js 為單執行緒,如果同步執行時遇到「阻塞」的程式,後續要執行的程式就會全部被卡住;為了解決這個問題, Node.js 在 v12 推出了 worker_threads
,這個 Module 讓 Node.js 可以做多執行緒的平行處理!
今天這篇文章會採用 Demo 的形式,讓大家理解程式運作的順序,而「阻塞」的程式則是選用
斐波那契數列(fibonacci sequence)
來模擬。
▋單執行緒會遇到什麼問題
單執行緒如果遇上需要高 CPU 運算的程式,那整體效能就會大幅下降;下面我們用一個簡單的程式來做說明:
上述程式的執行結果為:
42th Fibonacci Result:267914296
15th Fibonacci Result:610
被卡住的輕量級任務
你可以將程式中的 3 個 console.log 理解為:
- 42th Fibonacci:會讓程式阻塞的重量級運算。
- 15th Fibonacci:運算需要的時間不長,但被上面的程式卡住了。
- 被卡住的輕量級任務:只是簡單的輸出,卻被上面的程式卡的動彈不得。
▋多執行緒如何解決
既然知道 斐波那契數列(fibonacci sequence)
是阻塞的元兇,那我們可以把這個運算抽離出來,給新的執行緒來計算。
在實作方面,先新增一個 worker.js
的檔案,讓他處理由「主執行緒」指派的「新執行緒」;這裡的執行緒會透過 parentPort.postMessage
函數與「主執行緒」傳遞訊息。
接著我們新增一個 index.js
的檔案,來設計主執行緒的程式,筆者在這新增一個「runWorker」的函式,將會造成「阻塞」的程式交給它來執行。
經過這樣的調整後:
- 繁重的運算由「新執行緒」處理,且不會互相阻塞;解決了 Fibonacci 在「15th」的運算明明很快,但於單執行緒卻被「42th」拖到後面才執行的問題。
- 從下圖的運算結果,你可以觀察到主執行緒不會被阻塞。
▋結語
過去 Node.js 常常被說不適合執行高 CPU 運算的任務(因為會阻塞)。
但在導入 worker_threads
使其可以運用多執行緒後,我們只要將「高 CPU 運算」的任務交給其他執行緒處理,主執行緒就能繼續處理其他任務不被阻塞,以此提高 Server 的吞吐量。
▶︎ 如果這篇文章有幫助到你1. 可以點擊下方「Follow」來追蹤我~
2. 可以對文章拍手讓我知道 👏🏻你們的追蹤與鼓勵是我繼續寫作的動力 🙏🏼▶︎ 如果你對工程師的職涯感到迷茫1. 也許我在iT邦幫忙發表的系列文可以給你不一樣的觀點 💡
2. 也歡迎您到書局選購支持,透過豐富的案例來重新檢視自己的職涯