概述nodejs核心机制
nodejs
- Non-Blocking I/O Model
- Event Loop
- Event-Driven
- 基本架構
- 何為阻塞
- 代碼執行時
- 阻止事件循環的幾個維度
- Worker Pool
- npm模塊的風險
Non-Blocking I/O Model
non-blocking是指node.js進程中不同步等待執行非javascript操作(例如I/O)完成而繼續執行下一塊代碼的特性。
注:CPU密集型屬于javascript操作。
I/O通常指與磁盤與網絡的交互
非阻塞I/O模型使得nodejs支持高并發且非常適合于I/O密集型應用
Nodejs Event Loop and Worker Pool
共6個階段
- timers setTimeout與setInterval回調函數隊列
- pending callbacks 會在下一次loop中執行的系統級回調隊列。如TCP ECONNREFUSED -idle,prepare 內部使用
- poll 接收新的I/O事件。執行I/O相關回調。在這個階段node進程可能會阻塞
- check setImmediate回調會在這個階段執行
- close 一些關閉的回調。比如connect.on('close', () => {....})
注:process.nextTick不屬于任何一個階段,它是介于任意兩個階段之間,并且在階段切換時執行nextTick回調
Event-Driven
基本架構
- nodejs事件驅動架構中有兩種線程:事件循環線程(Event Loop)以及工作線程池(worker pool)
- Event Loop負責編排客戶端請求而后調度Worker Pool處理CPU密集型任務
注:因此nodejs并不是純粹的單線程語言!
何為阻塞
- 如果Event Loop執行回調或worker執行任務需要很長時間,即為阻塞。當發生阻塞時,主要會有兩點需要考慮:
- 性能:如果某worker線程定期執行heavyweight任務,會影響服務吞吐量(請求/秒)
- 安全性:假設某些輸入會引起程序阻塞,則存在被惡意客戶端利用并攻擊的風險。即拒絕服務攻擊。
代碼執行時
- 在Event Loop中同步執行常規的變量、方法的定義與調用,javascript所有回調以及非阻塞異步I/O如網絡I/O
- Worker Pool是libuv(線程池工作調度的c++庫)在Worker Pool中異步執行“昂貴”繁重的任務。node提供非阻塞I/O(操作系統不提供)API,以及CPU密集的I/O API
- I/O密集型API:
- DNS: dns.lookup()
- fs: fs.readFile(),除了那些顯示說明同步的方法
- CPU密集型API:
- crypto: crypto.pbkdf2()
- zlib: 除了那些顯示說明同步的方法
- I/O密集型API:
Event Loop實質
抽象來說,Event Loop維護掛起事件的隊列,Worker Pool維護掛起任務的隊列。
實際上,Event Loop并不是維護一個隊列。而是一個文件描述符的集合,這些文件描述符從系統級事件通知機制獲取比如epoll(linux),kqueue(OSX),IOCP(Windows)。這些文件描述符對應于某些網絡套接字以及node正在監視的文件等等。當某個描述符準備好時,Event Loop會將其轉換為合適的事件并執行對應的回調。
另外,Worker Pool維護的是一個真正的隊列。Worker會pop出隊列的task并執行,完成后會觸發Event Loop“至少一個事件已完成”的事件。
阻止事件循環的幾個維度
Worker Pool
nodejs默認的Worker Pool專門用于處理I/O任務,維護自己的線程池可以使用cluster模塊以及child_process模塊做自定義線程池。
Node服務器的吞吐量取決于WorkerPool的吞吐量。有效降低逐個任務時間開銷以及穩定任務時間開銷的變化將最大程度提升服務器的吞吐量。最常見的方法就是復雜重復型任務(比如數組迭代)做分區處理。
注:由于調度Worker Pool會增加額外的通信開銷,因為Worker Pool無法獲取主線程的命名空間從而無法直接讀取Javascript對象,所以需要序列化/反序列化導致增加通信成本。
npm模塊的風險
npm生態系統中存在數十萬個模塊為開發者提供了極大的便利,然而社區中npm包良莠不齊,因為無法較為準確的估計其使用Event Loop或者Worker Pool的成本而導致一些程序隱患。
總結
以上是生活随笔為你收集整理的概述nodejs核心机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MAC下载JDK及安装AndroidSt
- 下一篇: 为什么前端开发这么不稳定?