NodeJS 事件多路分解器與Reactor 模式

PY
3 min readMar 24, 2019

--

解析 NodeJS 底層架構

補充一下關於前一篇最後所提到的 nodejs 部分

Reactor 模式

反應器設計模式的目的是為了處理服務請求的併發,也就是當A跟B同時發請求到 server 端時,如何正確地回應這兩個請求。

阻塞 I/O 與非阻塞 I/O

先提到 NodeJS 如何處理I/O的,當遇到讀寫檔案、網路傳輸或是資料庫讀取等系統操作時,這時在電腦處理中是相當緩慢的。

阻塞 I/O 在與請求相對應的 function 調用時,將阻塞執行緒的執行,直到操作完成,這是為了防止併發的請求產生。

A ->         -> handle // 在資料庫查詢中
Server
B -> -> handle // 阻塞中,因為A正在查詢

於現在的操作系統中,大多數都採用非阻塞 I/O,在這個模式下,所有請求都立即返回結果,即使數據還未讀取或寫入,他會先調用預定地結果來代表說還沒抓到你要的數據,再以循環遍歷的方式去問說到底抓到了沒,這統稱為忙碌等待。

事件多路分解器 Event Demultiplexer

非阻塞 I/O 絕對不是處理 I/O 時最有效的解法,在循環訪問時鐵定會消耗大量的 CPU,這時出現了另一種處理機制,稱為同步事件多路分解器或是事件通知接口。

A ->        
Server -> watcher(handleA, handleB)
B ->

function 先註冊事件通知器 watcher 並阻塞,此時當事件完成了或是資源被抓到了就立即通知,這樣就能在同一個執行緒中處理多個 I/O 了。

Reactor 模式

所以回到標題,Reactor 設計模式就是利用這個同步事件多路分解器,來做執行緒的處理

  1. 當使用者提交 I/O 請求後(1),會註冊事件多路分解器,接下來這分解器會指定一個處理程序,以便完成後執行。
  2. 所以接下來 I/O 完成,事件處理器推送至 Event Queue 也就是上一篇提到的 Call Back(2),然後開始進入 Event Loop (3),並在完成後 Pop out
  3. 執行完成後的處理程序(4),此時會把控制權交給 Event Loop(5a),並進行循環(6),或是有新的 I/O 進來,繼續註冊多路分解器(5b)

Libuv

Node.js-libuv 是 Node.js 底層 I/O 引擎,libuv 實現了 Reactor 模式,提供了API接口,供Event loop, Event Queue, I/O 等操作

可以看到應用程式與 V8 與 LIBUV 透過 Node api 做綁定,然後 V8 再與應用程式進行交互

--

--