# 3.1 reactor反應堆模式
對每一個構架模式的分析,我們都使用參考文獻的分析風格,著重分析意圖、上下文、問題、解決方案、結構和實現 6個方面的內容。
##1. 意圖
在事件驅動的應用中,將一個或多個客戶的服務請求分離(demultiplex)和調度(dispatch)給應用程序。
##2. 上下文
在事件驅動的應用中,同步地、有序地處理同時接收的多個服務請求。
##3. 問題
在分布式系統尤其是服務器這一類事件驅動應用中,雖然這些請求最終會被序列化地處理,但是必須時刻準備著處理多個同時到來的服務請求。在實際應用 中,這些請求總是通過一個事件(如CONNECTOR、READ、WRITE等)來表示的。在有序地處理這些服務請求之前,應用程序必須先分離和調度這些 同時到達的事件。為了有效地解決這個問題,我們需要做到以下4方面:
為了提高系統的可測量性和反應時間,應用程序不能長時間阻塞在某個事件源上而停止對其他事件的處理,這樣會嚴重降低對客戶端的響應度。
為了提高吞吐量,任何沒有必要的上下文切換、同步和CPU之間的數據移動都要避免。
引進新的服務或改良已有的服務都要對既有的事件分離和調度機制帶來盡可能小的影響。
大量的應用程序代碼需要隱藏在復雜的多線程和同步機制之后。
##4. 解決方案
在一個或多個事件源上等待事件的到來,例如,一個已經連接的Socket描述符就是一個事件源。將事件的分離和調度整合到處理它的服務中,而將分離和調度機制從應用程序對特定事件的處理中分離開,也就是說分離和調度機制與特定的應用程序無關。
具體來說,每個應用程序提供的每個服務都有一個獨立的事件處理器與之對應。由事件處理器處理來自事件源的特定類型的事件。每個事件處理器都事先注冊 到Reactor管理器中。Reactor管理器使用同步事件分離器在一個或多個事件源中等待事件的發生。當事件發生后,同步事件分離器通知 Reactor管理器,最后由Reactor管理器調度和該事件相關的事件處理器來完成請求的服務。
##5. 結構
在Reactor模式中,有5個關鍵的參與者。
描述符(handle):由操作系統提供,用于識別每一個事件,如Socket描述符、文件描述符等。在Linux中,它用一個整數來表示。事件可以來自外部,如來自客戶端的連接請求、數據等。事件也可以來自內部,如定時器事件。
同步事件分離器(demultiplexer):是一個函數,用來等待一個或多個事件的發生。調用者會被阻塞,直到分離器分離的描述符集上有事件發生。Linux的select函數是一個經常被使用的分離器。
事件處理器接口(event handler):是由一個或多個模板函數組成的接口。這些模板函數描述了和應用程序相關的對某個事件的操作。
具體的事件處理器:是事件處理器接口的實現。它實現了應用程序提供的某個服務。每個具體的事件處理器總和一個描述符相關。它使用描述符來識別事件、識別應用程序提供的服務。
Reactor 管理器(reactor):定義了一些接口,用于應用程序控制事件調度,以及應用程序注冊、刪除事件處理器和相關的描述符。它是事件處理器的調度核心。 Reactor管理器使用同步事件分離器來等待事件的發生。一旦事件發生,Reactor管理器先是分離每個事件,然后調度事件處理器,最后調用相關的模 板函數來處理這個事件。
通過上述分析,我們注意到,是Reactor管理器而不是應用程序負責等待事件、分離事件和調度事件。實際上,Reactor管理器并沒有被具體的 事件處理器調用,而是管理器調度具體的事件處理器,由事件處理器對發生的事件做出處理。這就是類似Hollywood原則的“反向控制”。應用程序要做的 僅僅是實現一個具體的事件處理器,然后把它注冊到Reactor管理器中。接下來的工作由管理器來完成。這些參與者的相互關系如圖2-1所示。
現在結合第1章分析的框架五元素來看一下Reactor構架模式的參與者與框架五元素之間的關系:Reactor構架模式的具體實現對應了元素1; 事件處理器接口對應元素2;具體的事件處理器對應元素3;Reactor管理器使用了Hollywood原則,可以認為和元素5對應;元素4的功能相對不 明顯,沒有明確的對應關系。
如果還是沒有理解Reactor構架模式,沒有關系,源代碼會說明所有問題。此時可再分析一遍Reactor構架模式,然后繼續以下內容。


- 封面
- 1 Libevent官方
- 2 epoll
- 2.1 流-IO操作-阻塞
- 2.2 解決阻塞死等待的辦法
- 2.3 什么是epoll
- 2.4 epollAPI
- 2.5 觸發模式
- 2.6 簡單的epoll服務器
- 3 epoll和reactor
- 3.1 reactor反應堆模式
- 3.2 epoll的反應堆模式實現
- 4 event_base
- 4.1 創建event_base
- 4.2 檢查event_base后端
- 4.3 釋放event_base
- 4.4 event_base優先級
- 4.5 event_base和fork
- 5 事件循環event_loop
- 5.1 運行循環
- 5.2 停止循環
- 5.3 轉儲event_base的狀態
- 6 事件event
- 6.1 創建事件
- 6.2 事件的未決和非未決
- 6.3 事件的優先級
- 6.4 檢查事件狀態
- 6.5 一次觸發事件
- 6.6 手動激活事件
- 6.7 事件狀態之間的轉換
- 7 數據緩沖Bufferevent
- 7.1 回調和水位
- 7.2 延遲回調
- 7.3 bufferevent 選項標志
- 7.4 使用bufferevent
- 7.5 通用bufferevent操作
- 7.5.1 釋放bufferevent操作
- 7.5.2 操作回調、水位和啟用/禁用
- 7.5.3 操作bufferevent中的數據
- 7.5.4 bufferevent的清空操作
- 8 數據封裝evBuffer
- 8.1 創建和釋放evbuffer
- 8.2 evbuffer與線程安全
- 8.3 檢查evbuffer
- 8.4 向evbuffer添加數據
- 8.5 evbuffer數據移動
- 8.6 添加數據到evbuffer前
- 8 鏈接監聽器evconnlistener
- 8.1 創建和釋放 evconnlistener
- 8.2 啟用和禁用 evconnlistener
- 8.3 調整 evconnlistener 的回調函數
- 8.4 檢測 evconnlistener
- 8.5 偵測錯誤
- 9 libevent常用設置
- 9.1 日志消息回調設置
- 9.2 致命錯誤回調設置
- 9.3 內存管理回調設置
- 9.4 鎖和線程的設置
- 9.5 調試事件的使用
- 10 基于libevent服務器
- 10.1 Hello_World服務器(基于信號)
- 10.2 基于事件服務器
- 10.3 回顯服務器
- 10.3 libevent實現http服務器