Reactor pattern

這篇 paper

問題 & 情境

Reactor pattern 處理一個 application 收到從一個或多個 client 同時(concurrently)送 request 的情況。

分散式環境的 server 必須處理多個送 request 過來的 client。為了處理 request,server 必須 demultiplex 以及 dispatch request 給對應的 service。設計 demultiplexing 及 dispatching 需考量:

  • Availability
    server 在等待某些 request 時(例如 server 與 client 間需要多步驟溝通,server 正在等 client 的某個步驟),server 依然能處理收到的 request,不能因為處理某個 request 而 block 住,不然會卡到對其他 request 的 response。
  • Efficiency
    server 要最小化 latency、最大化 throughput 以及避免不必要的 CPU 使用。
  • Programming simplicity
    顧名思義,程式寫得愈簡單愈好。
  • Adaptability
    容易新增或改進 service,修改最少現有的 code 就能加新功能或改進功能,例如新增 service 不用修改底層的 dispatching 機制。
  • Portability
    容易 porting 到其他 OS 平台等。

Solution

整合 demultiplexing 以及 dispatching 並且 decouple 通用的 event demultiplexing & dispatching 以及處理 request 的 service 實作邏輯、屬於應用邏輯的部份。讓 dispatch 歸 dispatch,應用邏輯歸應用邏輯,兩邊別混在一起。

Structure

看圖說故事比較容易,圖片出處

Reactor

  • Handle
    • 代表由 OS 管理的 resource,例如 network、file 等 resource。
    • 像 Linux 用 file descriptor 代表 file、socket 等等,Windows 用各種 handle 代表 resource。
  • Synchronous Event Demultiplexer
    • 負責看一堆 handle 有沒有人有 event、可以動作了。
    • 如果沒人可以動會 block 住,有人可以動時會 return,例如處理 IO event 的 select()
  • Initiation Dispatcher
    • 提供 register、remove event handler 以及 dispatch event 的介面。
    • Synchronous Event Demultiplexer 收到 event 時會通知 Initiation Dispatcher,Initiation Dispatcher dispatch event 給處理的 event handler。
  • Event Handler
    • 定義 event handler 的介面。
  • Concrete Event Handler
    • 繼承 Event Handler,實際實作處理 event 的邏輯。

流程

  1. application 向 Initiation Dispatcher 註冊 Concrete Event Handler,告訴 Initiation Dispatcher 這個 handler 處理哪種 event。
  2. application call Initiation Dispatcher 的 handle_events() 進入 event loop。Initiation Dispatcher 由 Event Handler 取得 Handle 交給 Synchronous Event Demultiplexer 等待 event。
  3. event 發生時 Synchronous Event Demultiplexer 通知 Initiation Dispatcher(以 select() 來說是 return)。
  4. Initiation Dispatcher call 對應 Event Handler 的 function 來處理 event。

Reactor

優缺點

優點

  • decouple 了 application 功能上的實作邏輯以及與 application 無關的 demultiplexing & dispatching 機制,各自負責各自的事。
  • 區分多個 service、各 service 負責自己相關的事情,讓 event-driven application 有較好的模組化並且能重複使用模組。
  • 增加 portability。Initiation Dispatcher 的 interface 不受限於特定 OS,可在不同的 demultiplexing system call 重複使用。
  • Initiation Dispatcher 的 event loop 依序 call event handler 減少複雜的 synchronization 機制。

缺點

  • 只在有提供 Handle 的 OS 上有效率。
  • non-preemptive:single thread application 中 Event Handler 執行時是無法被中斷、改去做其他事的,所以 Event Handler 處理 event 時不能被 block 住,不然整個 process 就卡住了。所以需要較長時間處理 event 的 application 不適合 reactor pattern。
  • reactor pattern 會用在 framework 裡,導致 control flow 在 application 的 handler 及 framework 間跳來跳去,對於寫 application 、不熟悉 framework 運作或者根本看不到 framework 的 code 的開發者較難以 debug。

實作細節

流程上雖然一開始就向 Dispatcher 註冊完 event handler,但也可能是某種 event handler 處理 event 時才生另外的 event handler 並且註冊,即註冊及移除 event handler 是動態的。例如 Linux 處理 accept socket connection 的 event handler 在 accept() 後才生處理 client request 的 event handler 並向 Dispatcher 註冊,之後由該 event handler 處理 client 的 request。