libevent源碼分析(二) Reactor模式

由於libeventlibevent本身就是一個ReactorReactor,所以瞭解ReactorReactor這樣一個應用於服務端的開發設計模式很有必要。

1.ReactorReactor模式

藉由WikipediaWikipedia上的解釋:

"The reactor design pattern is an event handling pattern for handling service requests delivered concurrently by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to associated request handlers."

從這個描述中我們能瞭解到ReactorReactor模式是事件驅動的,有一個或多個併發輸入源,有一個 ServiceService HandlerHandler,有多個 RequestRequest HandlerHandler;這個ServiceService HandlerHandler會同步的將輸入的請求(EventEvent)多路複用的分發給相應的RequestRequest HandlerHandler

2.ReactorReactor模式的事件處理機制

不同於普通的函數調用,應用程序不是主動的調用某個APIAPI完成處理,恰恰相反;ReactorReactor 逆置了事件處理流程,應用程序需要提供相應的接口並註冊到 ReactorReactor 上,如果相應的事件發生,ReactorReactor 將主動調用應用程序註冊的接口,這些接口又稱爲CallbackCallback函數(回調函數)。使用 libeventlibevent 也是想 libeventlibevent 框架註冊相應的事件和回調函數;當這些事件發生時,libeventlibevent 會調用這些回調函數處理相應的事件(I/OI/O 讀寫、定時和信號)。

3.ReactorReactor模式具備的優點
ReactorReactor 模式是編寫高性能網絡服務器的必備技術之一,它具有如下的優點:

  • 1)響應快,不必爲單個同步時間所阻塞,雖然 ReactorReactor 本身依然是同步的;
  • 2)編程相對簡單,可以最大程度的避免複雜的多線程及同步問題,並且避免了多線程/
    進程的切換開銷;
  • 3)可擴展性,可以方便的通過增加 ReactorReactor 實例個數來充分利用 CPUCPU 資源;
  • 4)可複用性,reactorreactor 框架本身與具體事件處理邏輯無關,具有很高的複用性;

4.ReactorReactor模式框架

使用ReactorReactor模型必備的幾個組件:事件源、ReactorReactor框架、多路複用機制以及事件處理機制,如下圖:

在這裏插入圖片描述
(一)事件源
LinuxLinux 上是文件描述符,WindowsWindows 上就是 SocketSocket 或者 HandleHandle 了,這裏統一稱爲“句柄 集”;程序在指定的句柄上註冊關心的事件,比如 I/OI/O 事件。

(二)eventevent demultiplexerdemultiplexer——事件多路分發機制
由操作系統提供的I/0I/0多路複用機制,比如selectselectpollepollpoll以及epoll

  • 1.首先,程序將其關心的eventevent註冊到eventevent demultiplexerdemultiplexer
  • 2.當有事件到達時,eventevent demultiplexerdemultiplexer會發出一個通知,告訴HandleHandle在已註冊的eventevent中,有一個或多個eventevent準備就緒;
  • 3.程序收到通知後,以非阻塞的方式對事件進行處理

對應到 libeventlibevent 中,依然是 selectselectpollpollepollepoll 等,但是 libeventlibevent 使用結構體 eventopeventop 進行了封裝,以統一的接口來支持這些 I/OI/O 多路複用機制,達到了對外隱藏底層系統機制的目的。

(三)ReactorReactor–反應器
ReactorReactor,事件處理的接口。內部使用eventevent demultiplexerdemultiplexer進行註冊、註銷事件;並運行事件循環;當有事件準備就緒,調用註冊事件的回調函數處理事件。

對應到libeventlibevent,就是eventevent_ basebase結構體。

常用的ReactorReactor聲明:

class Reactor {
public:
	int register_handler(Event_Handler *pHandler, int event); 
	int remove_handler(Event_Handler *pHandler, int event); 
	void handle_events(timeval *ptv); 
	// ... 
};

(四)EventEvent HandleHandle—事件處理程序
事件處理程序提供了一組接口,分別對應於不同類型的事件;當有事件發生時,ReactorReactor調用相應的事件處理函數,通常會綁定一個有效的句柄。

對應到libeventlibevent,就是eventevent結構體。

常用的EventEvent HandleHandle聲明:

class Event_Handle{
public:
	virtual void handle_read() = 0; 
	virtual void handle_write() = 0; 
	virtual void handle_timeout() = 0; 
	virtual void handle_close() = 0; 
	virtual HANDLE get_handle() = 0; 
	// ... 
};
class Event_Handle{
public:
	// events maybe read/write/timeout/close .etc 
	virtual void handle_events(int events) = 0; 
	virtual HANDLE get_handle() = 0; 
	// ... 
};

5.ReactorReactor事件處理流程
如下圖:

在這裏插入圖片描述
6.與ProactorProactor模式區別

  • (1) ReactorReactor模式是基於同步I/OI/O的,而ProactorProactor則是基於異步I/OI/O

  • (2)上面我們提到ReactorReactor模式是應用程序註冊事件到ReactorReactor,然後當事件發生時,ReactorReactor調用其回調函數進行事件處理,由回調函數來進行讀寫等操作;而在ProactorProactor模式中,事件處理者直接發起一個異步讀寫操作(相當於請求),而實際的工作由操作系統完成。

  • (3)兩種模式的處理步驟
    標準的ReactorReactor步驟:
    1)等待事件(ReactorReactor完成)
    2)將”就緒”事件發給事件註冊的事件處理者或者回調函數(ReactorReactor完成)
    3)讀數據(用戶完成)
    4)處理數據(用戶完成)
    模擬的ProactorProactor步驟:
    1)等待事件(ProactorProactor完成)
    2)讀數據(ProactorProactor完成)
    3)把數據準備好的消息傳給事件處理者(ProactorProactor完成)
    4)處理數據(用戶完成)

  • (4)兩者區別
    1.ReactorReactor模式更多的是關心事件的發生,將如何處理事件的後續交給了用戶態的應用來處理;而ProactorProactor則☞關心由操作系統完成異步非阻塞操作之後的結果
    2.ProactorProactor場景中只能夠使用異步非阻塞的syscallsyscall(系統調用),而ReactorReactor的場景中更多地是使用非阻塞同步的syscallsyscall(系統調用);

參考文章:關於Reactor和Proactor的區別
libevent源碼深度剖析二

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章