libevent 的Reactor模型

libevent的設計是一個典型的Reactor模型,理解Reactor模型是理解libevent的基石,所以本節主要介紹典型的事件驅動設計模式---Reactor模式react

The Reactor design pattern handles service requests that are delivered concurrently to an application by one or more clients.git

reactor.pdf第一句話就直接說到Reactor 設計模式能夠爲一個應用同時處理一個或者多個客戶端請求服務github

Reactor的事件處理機制

Reactor Bing 中文翻譯爲 "反應堆,反應器",是一種事件驅動機制。與普通函數調用的不一樣之處在於:應用程序不是主動的調用某個API完成處理,而是偏偏相反,Reactor逆置了事件處理流程,應用程序須要提供相應的接口並註冊到Reactor上,若是相應的事件發生,Reactor將主動調用應用程序註冊的接口,這些接口又稱爲"callback function"(回調函數).編程

在使用libevent時,須要向libevent框架註冊相應的事件和會調函數,當註冊的相應事件發生時,libevent會調用回調函數處理相應的時間(I/O讀寫,定時器,信號)設計模式

用"好萊塢原則"來形容Reactor再合適不過了: 不要打電話給咱們,咱們會打電話通知你。數組

Reactor模式結構

在Reactor模式中,有5個關鍵參與者。服務器

  • 描述符(handle):由操做系統提供,用於識別每一個事件,如Socket描述符、文件描述符等。在Linux中,它用一個整數來表示。事件能夠來自外部,如來自客戶端的鏈接請求、數據等。事件也能夠來自內部,如定時器事件。
  • 同步事件分離器(synchronous event demultiplexer):是一個函數,用於等待一個或多個事件的發生。調用者會被阻塞,直到分離器分離的描述符集上有事件發生。Linux的select函數是一個常常被使用的分離器。
  • 事件處理器接口(event handler):是有一個或多個模板函數組成的接口。這些模板函數描述了和應用程序相關的對於某個事件的操做。
  • 具體的事件處理器(concrete event handler):是事件處理器接口的實現,它實現了應用程序提供的某個服務。每一個具體的事件處理器總和一個描述符相關。它使用描述符來識別事件、識別應用程序提供的服務。
  • Reactor管理器(dispatcher):定義了一些接口,用於應用程序控制事件調度,以及應用程序註冊、刪除事件處理器和相關的描述符。它是事件處理器的調度核心。Reactor管理器使用同步事件分離器來等待事件的發生。一旦事件發生,Reactor管理器先是分離每一個事件,而後調度事件處理器,最後調用相關模板函數來處理這個事件。

Reactor模型總體框架

在上圖中,能夠看到Rector管理器(dispatcher)是Reactor模式中最爲關鍵的角色,它是該模式最終向用戶提供接口的類。用戶能夠向Reactor中註冊event handler,而後Reactor在react的時候,發現用戶註冊的fd有事件發生,就會調用用戶的事件處理函數。下面是一個典型的reactor聲明方式:網絡

class Reactor
{
public:
	//構造函數
	Reactor();
    //析構函數
    ~Reactor();
    //向reactor中註冊關注事件evt的handler(可重入)
    //@param handler 要註冊的事件處理器
    //@param evt 要關注的事件
    //@retval 0 註冊成功
    //@retval -1 註冊出錯
    int RegisterHandler(EventHandler *handler, event_t evt);

    //從reactor中移除handler
    //param handler 要移除的事件處理器
    //retval 0 移除成功
    //retval -1 移除出錯
    int RemoveHandler(EventHandler *handler);

    //處理事件,回調註冊的handler中相應的事件處理函數
    //@param timeout 超時事件(毫秒)
    void HandlerEvents(int timeout = 0);

private:
	ReactorImplementation *m_reactor_impl; //reactor的實現類
}

SynchrousEventDemultiplexer也是Reactor中一個比較重要的角色,它是Reactor用來檢測用戶註冊的fd上發生的事件的利器,經過Reactor得知了那些fd上發生了什麼樣的事件,而後以這些爲依據,來多路分發事件,回調用戶事件處理函數。下面是一個簡單的設計:多線程

class EventDemultiplexer
{
public:
    /// 獲取有事件發生的全部句柄以及所發生的事件
    /// @param  events  獲取的事件
    /// @param  timeout 超時時間
    /// @retval 0       沒有發生事件的句柄(超時)
    /// @retval 大於0   發生事件的句柄個數
    /// @retval 小於0   發生錯誤
    virtual int WaitEvents(std::map<handle_t , event_t> * events, int timeout = 0) = 0;
    /// 設置句柄handle關注evt事件
    /// @retval 0     設置成功
    /// @retval 小於0 設置出錯
    virtual int RequestEvent(handle_t handle, event_t evt) = 0;

    /// 撤銷句柄handle對事件evt的關注
    /// @retval 0     撤銷成功
    /// @retval 小於0 撤銷出錯
    virtual int UnrequestEvent(handle_t handle, event_t evt) = 0;
};

Event Handler事件處理程序提供一組接口,每一個接口對應了一種類型的事件,供Reactr在相應的事件發生時調用,執行相應的事件處理。一般它會綁定一個有效的句柄。對應到libevent中,就是event結構體。下面是典型的Event Handler類兩種聲明方式。app

class Event_Handler
{
public:
	//處理讀事件的回調函數
	virtual void handle_read() = 0;
    //處理寫事件的回調函數
    virtual void handle_write() = 0;
    //處理超時的回調函數
    virtual void handle_timeout() = 0;
    //關閉對應的handle句柄
    virtual void handle_close() = 0;
    //獲取該handler所對應的句柄
    virtual HANDLE get_handle() = 0;
};
________________________________________________________________________________

class Event_Handler
{
public:
	//event maybe read/write/timeout/close .etc
    virtual void hand_events(int events) = 0;
    virtual HANDLE get_handle() = 0;
}

ConcreteEventHandler具體事件處理器是EventHanler的子類,EventHandler是Reactor所用來規定接口的基類,用戶本身的事件處理器都必須從EventHandler繼承。

Reactor事件處理流程

下面這幅圖展現了應用程序在參與在Reactor模式下的協做交互 應用程序協做交互圖

Reactor模式的優勢

Reactor模式是編寫高性能網絡服務器的必備技術之一,它具備以下優勢:

  • 響應快,沒必要爲單個同步時間所阻塞,雖然Reactor自己依然是同步的
  • 編程相對簡單,能夠最大程度的避免複雜的多線程及同步問題,而且避免多線程或者多進程的切換開銷
  • 可擴展性,能夠方便的經過增長Reactor實例個數來充分利用CPU資源
  • 可複用性,Reactor框架自己與具體事件處理邏輯無關,具備很高的複用性

免責聲明:本文部份內容整理參考來自互聯網,本着分享學習的目的,並沒有商用,若有侵犯之處能夠與我聯繫並刪除。

參考來源:

http://www.laputan.org/pub/sag/reactor.pdf

http://www.wuzesheng.com/?p=1607

http://blog.csdn.net/sparkliang/article/details/4957744


若是以爲有用,能夠Github上star並鼓勵我,或者Pull Reauest 修正

相關文章
相關標籤/搜索