Reactor和Proactor對比以及優缺點 (netty的底層原理reactor模型)

IO設計模式:Reactor和Proactor對比

時接觸的開源產品如Redis、ACE,事件模型都使用的Reactor模式;而同樣做事件處理的Proactor,由於操作系統的原因,相關的開源產品也少;這裏學習下其模型結構,重點對比下兩者的異同點;

反應器Reactor
Reactor模式結構

Reactor

Reactor包含如下角色:

Handle 句柄;用來標識socket連接或是打開文件;
Synchronous Event Demultiplexer:同步事件多路分解器:由操作系統內核實現的一個函數;用於阻塞等待發生在句柄集合上的一個或多個事件;(如select/epoll;)
Event Handler:事件處理接口
Concrete Event HandlerA:實現應用程序所提供的特定事件處理邏輯;
Reactor:反應器,定義一個接口,實現以下功能: 
1)供應用程序註冊和刪除關注的事件句柄; 
2)運行事件循環; 
3)有就緒事件到來時,分發事件到之前註冊的回調函數上處理;
 

「反應」器名字中」反應「的由來: 
「反應」即「倒置」,「控制逆轉」,具體事件處理程序不調用反應器,而是由反應器分配一個具體事件處理程序,具體事件處理程序對某個指定的事件發生做出反應;這種控制逆轉又稱爲「好萊塢法則」(不要調用我,讓我來調用你)

業務流程及時序圖

seq_Reactor  


應用啓動,將關注的事件handle註冊到Reactor中;
調用Reactor,進入無限事件循環,等待註冊的事件到來;
事件到來,select返回,Reactor將事件分發到之前註冊的回調函數中處理;

主動器Proactor

Proactor模式結構

Proactor

Proactor主動器模式包含如下角色

Handle 句柄;用來標識socket連接或是打開文件;
Asynchronous Operation Processor:異步操作處理器;負責執行異步操作,一般由操作系統內核實現;
Asynchronous Operation:異步操作
Completion Event Queue:完成事件隊列;異步操作完成的結果放到隊列中等待後續使用
Proactor:主動器;爲應用程序進程提供事件循環;從完成事件隊列中取出異步操作的結果,分發調用相應的後續處理邏輯;
Completion Handler:完成事件接口;一般是由回調函數組成的接口;
Concrete Completion Handler:完成事件處理邏輯;實現接口定義特定的應用處理邏輯;
業務流程及時序圖

seq_Proactor

應用程序啓動,調用異步操作處理器提供的異步操作接口函數,調用之後應用程序和異步操作處理就獨立運行;應用程序可以調用新的異步操作,而其它操作可以併發進行;
應用程序啓動Proactor主動器,進行無限的事件循環,等待完成事件到來;
異步操作處理器執行異步操作,完成後將結果放入到完成事件隊列;
主動器從完成事件隊列中取出結果,分發到相應的完成事件回調函數處理邏輯中;

 

對比兩者的區別


主動和被動
以主動寫爲例: 
Reactor將handle放到select(),等待可寫就緒,然後調用write()寫入數據;寫完處理後續邏輯; 
Proactor調用aoi_write後立刻返回,由內核負責寫操作,寫完後調用相應的回調函數處理後續邏輯;

可以看出,Reactor被動的等待指示事件的到來並做出反應;它有一個等待的過程,做什麼都要先放入到監聽事件集合中等待handler可用時再進行操作; 
Proactor直接調用異步讀寫操作,調用完後立刻返回;

實現
Reactor實現了一個被動的事件分離和分發模型,服務等待請求事件的到來,再通過不受間斷的同步處理事件,從而做出反應;

Proactor實現了一個主動的事件分離和分發模型;這種設計允許多個任務併發的執行,從而提高吞吐量;並可執行耗時長的任務(各個任務間互不影響)

優點
Reactor實現相對簡單,對於耗時短的處理場景處理高效; 
操作系統可以在多個事件源上等待,並且避免了多線程編程相關的性能開銷和編程複雜性; 
事件的串行化對應用是透明的,可以順序的同步執行而不需要加鎖; 
事務分離:將與應用無關的多路分解和分配機制和與應用相關的回調函數分離開來,

Proactor性能更高,能夠處理耗時長的併發場景;

缺點
Reactor處理耗時長的操作會造成事件分發的阻塞,影響到後續事件的處理;

Proactor實現邏輯複雜;依賴操作系統對異步的支持,目前實現了純異步操作的操作系統少,實現優秀的如windows IOCP,但由於其windows系統用於服務器的侷限性,目前應用範圍較小;而Unix/Linux系統對純異步的支持有限,應用事件驅動的主流還是通過select/epoll來實現;

適用場景
Reactor:同時接收多個服務請求,並且依次同步的處理它們的事件驅動程序; 
Proactor:異步接收和同時處理多個服務請求的事件驅動程序;

 

        最後我們知道linux系統提供的異步I/O,只支持O_DIRECT,不能帶緩存。因此出現了開源庫libeio,它和Linux的異步I/O一樣也是用多線程模擬,但是更高效。下圖是libeio的異步I/O實現,是不是很像Proactor模式啊。

 最後我們知道linux系統提供的異步I/O,只支持O_DIRECT,不能帶緩存。因此出現了開源庫libeio,它和Linux的異步I/O一樣也是用多線程模擬,但是更高效。下圖是libeio的異步I/O實現,是不是很像Proactor模式啊。

 

 

--------------------  轉載: 原文:https://blog.csdn.net/wanbf123/article/details/78062802?utm_source=copy