Reactor模式是處理并發I/O比較常見的一種模式,用于同步I/O,中心思想是将所有要處理的I/O事件注冊到一個中心I/O多路複用器上,同時主線程阻塞在多路複用器上;一旦有I/O事件到來或是準備就緒(差別在于多路複用器是邊沿觸發還是水準觸發),多路複用器傳回并将相應I/O事件分發到對應的處理器中。
Reactor是一種事件驅動機制,和普通函數調用的不同之處在于:應用程式不是主動的調用某個API完成處理,而是恰恰相反,Reactor逆置了事件處理流程,應用程式需要提供相應的接口并注冊到Reactor上,如果相應的事件發生,Reactor将主動調用應用程式注冊的接口,這些接口又稱為“回調函數”。用“好萊塢原則”來形容Reactor再合适不過了:不要打電話給我們,我們會打電話通知你。
Reactor模式與Observer模式在某些方面極為相似:當一個主體發生改變時,所有依屬體都得到通知。不過,觀察者模式與單個事件源關聯,而反應器模式則與多個事件源關聯 。
Reactor 結構

上圖是 Reactor 模型,主要涉及的類:
Initiation Dispatcher:EventHandler 的容器,用來注冊、移除 EventHandler 等;另外,它作為 Reactor 模式的入口調用 Synchronous Event Demultiplexer 的 select 方法以阻塞等待事件的傳回,當阻塞事件傳回時,将事件發生的 Handle 分發到相應的 EvenHandler 處理。
Even Handler:定義了事件處理的方法。
Handle:即作業系統中的句柄,是對資源在作業系統層面上的一種抽象,它可以是打開的檔案、一個連接配接(Socket)、Timer等。
Synchronous Event Demultiplexer:使用一個事件循環 ,以阻止所有的資源。當可以啟動一個同步操作上的資源不會阻塞,多路分解器發送資源到分發器。
Reactor 時序圖
- 初始化 InitationDispatcher,并初始化一個Handle到EventHandler的Map。
-
注冊 EvenHandler 到 InitationDispatcher,每個 EventHandler 包含對相應 Handle
的引用,進而建立Handle到EventHandler的映射(Map)。
-
調用 InitiationDispatcher 的 handle_events() 方法以啟動 Event Loop。在 Event
Loop 中,調用 select()方法(Synchronous Event Demultiplexer)阻塞等待Event發生。
-
當某個或某些 Handle 的 Event 發生後,select() 方法傳回,InitiationDispatcher
根據傳回的Handle找到注冊的 EventHandler ,并回調該 EventHandler 的 handle_events()
方法。
-
在 EventHandler 的 handle_events() 方法中還可以向 InitiationDispatcher 中注冊新的
Eventhandler,比如對 AcceptorEventHandler 來說,當有新的 client 連接配接時,它會産生新的EventHandler 以處理新的連接配接,并注冊到 InitiationDispatcher 中。
單線程模型
這是最簡單的單Reactor單線程模型。Reactor線程是個多面手,負責多路分離套接字,Accept新連接配接,并分派請求到處理器鍊中。該模型适用于處理器鍊中業務處理元件能快速完成的場景。不過這種單線程模型不能充分利用多核資源,是以實際使用的不多。
多線程模型(單Reactor)
相比上一種模型,該模型在事件處理器(Handler)鍊部分采用了多線程(線程池),也是後端程式常用的模型。
多線程模型(多Reactor)
這個模型比起第二種模型,它是将Reactor分成兩部分,mainReactor負責監聽并accept新連接配接,然後将建立的socket通過多路複用器(Acceptor)分派給subReactor。subReactor負責多路分離已連接配接的socket,讀寫網絡資料;業務處理功能,其交給worker線程池完成。通常,subReactor個數上可與CPU個數等同。
Reactor 的優缺點
優點:
大多數設計模式的共性:解耦、提升複用性、子產品化、可移植性、事件驅動、細力度的并發控制等。
更為顯著的是對性能的提升,即不需要每個 Client 對應一個線程,減少線程的使用。
缺點:
相比傳統的簡單模型,Reactor增加了一定的複雜性,因而有一定的門檻,并且不易于調試。
Reactor模式需要底層的Synchronous Event Demultiplexer支援,比如Java中的Selector支援,作業系統的select系統調用支援,如果要自己實作Synchronous Event Demultiplexer可能不會有那麼高效。