Linux -- Proactor(及其與Reactor的比較)

高併發服務器常由多線程+IO複用服務器(one event loop per thread)html

兩種I/O多路複用模式:Reactor和Proactor

通常地,I/O多路複用機制都依賴於一個事件多路分離器(Event Demultiplexer)。分離器對象可未來自事件源的I/O事件分離出來,並分發到對應的read/write事件處理器(Event Handler)。開發人員預先註冊須要處理的事件及其事件處理器(或回調函數);事件分離器負責將請求事件傳遞給事件處理器。兩個與事件分離器有關的模式是Reactor和Proactor。Reactor模式採用同步IO,而Proactor採用異步IO。web

 

在Reactor中,事件分離器負責等待文件描述符或socket爲讀寫操做準備就緒,而後將就緒事件傳遞給對應的處理器,最後由事件處理器負責完成實際的讀寫工做。而在Proactor模式中,處理器或者兼任處理器的事件分離器,只負責發起異步讀寫操做。IO操做自己由操做系統來完成。傳遞給操做系統的參數須要包括用戶定義的數據緩衝區地址和數據大小,操做系統才能從中獲得寫出操做所需數據,或寫入從socket讀到的數據。事件分離器捕獲IO操做完成事件,而後將事件傳遞給對應處理器。好比,在windows上,處理器發起一個異步IO操做,再由事件分離器等待IOCompletion事件。典型的異步模式實現,都創建在操做系統支持異步API的基礎之上,咱們將這種實現稱爲「系統級」異步或「真」異步,由於應用程序徹底依賴操做系統執行真正的IO工做。以讀操做爲例:編程

 

在Reactor中實現讀:segmentfault

- 註冊讀就緒事件和相應的事件處理器windows

- 事件分離器等待事件設計模式

- 事件到來,激活分離器,分離器調用事件對應的處理器。服務器

- 事件處理器完成實際的讀操做,處理讀到的數據,註冊新的事件,而後返還控制權。網絡

 

在Proactor中實現讀:多線程

- 處理器發起異步讀操做(注意:操做系統必須支持異步IO)。在這種狀況下,處理器無視IO就緒事件,它關注的是完成事件。併發

- 事件分離器等待操做完成事件

- 在分離器等待過程當中,操做系統利用並行的內核線程執行實際的讀操做,並將結果數據存入用戶自定義緩衝區,最後通知事件分離器讀操做完成。

- 事件分離器呼喚處理器。

- 事件處理器處理用戶自定義緩衝區中的數據,而後啓動一個新的異步操做,並將控制權返回事件分離器。

 

經過上例能夠看出,兩個模式的相同點,都是對某個IO事件的事件通知(即告訴某個模塊,這個IO操做能夠進行或已經完成)。在結構上,二者也有相同點:demultiplexor負責提交IO操做(異步)、查詢設備是否可操做(同步),而後當條件知足時,就回調handler;不一樣點在於,異步狀況下(Proactor),當回調handler時,表示IO操做已經完成;同步狀況下(Reactor),回調handler時,表示IO設備能夠進行某個操做(can read or can write)。

 

使用Proactor框架和Reactor框架均可以極大的簡化網絡應用的開發,但它們的重點卻不一樣。Reactor框架中用戶定義的操做是在實際操做以前調用的。好比你定義了操做是要向一個SOCKET寫數據,那麼當該SOCKET能夠接收數據的時候,你的操做就會被調用;而Proactor框架中用戶定義的操做是在實際操做以後調用的。好比你定義了一個操做要顯示從SOCKET中讀入的數據,那麼當讀操做完成之後,你的操做纔會被調用。

 

Proactor和Reactor都是併發編程中的設計模式。在我看來,他們都是用於派發/分離IO操做事件的。這裏所謂的IO事件也就是諸如read/write的IO操做。"派發/分離"就是將單獨的IO事件通知到上層模塊。兩個模式不一樣的地方在於,Proactor用於異步IO,而Reactor用於同步IO。目前應用最普遍的是Reactor模boost::asio,ACE和Windows I/O Completion Ports 實現了Proactor 模式,應用面彷佛要窄一些。

 

Proactor (論文翻譯提要)

原文: http://www.cs.wustl.edu/~schmidt/PDF/proactor.pdf

結構

1. proacitve initiator (Web server application’s main thread)

       proactive Initiator是應用中啓動異步操做的實體.proactive initiator註冊一個completion handler和一個completion dispatcher,以及一個asynchronous Operation Processor, asynchronous Operation Processor的做用是當操做完成將會通知.

2.Completion Handler(the acceptor and http handler)

       Proactor模式使用completion handler接口用來得到異步操做完成的通知.

3.Asynchronous Operation

        異步操做,由系統API實現,如async_read,async_write,async_accept等.異步操做用來執行異步請求(如i/o或定時器.).當應用請求異步操做時,該操做不會佔用應用(主)線程.所以,從整個應用的角度來看,操做表現爲異步.當異步操做完成,異步操做處理器(Asynchronous         Operation Processor)將通知完成操做分發器(Completion Dispatcher)

4. Asynchronous Operation Processor(操做系統)

        異步操做由異步操做處理器(Asynchronous Operation Processor)執行完成.該組件由操做系統實現.

5. Completion Dispatcher (the Notification Queue)

        完成分發器的做用是,當異步操做完成時,把Completion handler返回給應用,即proacitve initiator

流程

1.主動啓動器(proacitve initiator)啓動操做

        爲了表現爲異步操做,應用在異步操做處理器中啓動操做.舉例:一個web server向OS請求經過網絡向某個特定的socket connetion發送一個文件.web server應該指定當操做完成去通知哪個completion handler,以及當文件傳送完成後哪個completion dispatcher去callback.

2.異步操做處理器執行操做.

       當應用在異步操做處理器上請求操做,異步操做處理器異步地執行這些操做.現代操做系統在內核中提供了異步IO.

3.異步操做處理器通知完成分發器

       當異步操做完成,異步操做處理器檢索特定的completion handler和completion dispatcher.(在第1步時指定的).而後異步操做處理器把異步操做的結果(the result of the Asynchronous Operation)和要返回的comletion handler(the Completion Handler to call back)傳遞給completion dispatcher.舉例:當文件成功地被異步發送出,異步操做處理器將會報告完成狀態(成功或失敗),同時the number of bytes written to the network connection.

4.完成分發器通知應用程序.

        舉例:例如一個異步讀操做完成後,completion handler 將被傳入一個指向newly arrived data的指針.

 

如下是POSA2中的proactor模型

http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/overview/core/async.html

http://www.javashuo.com/article/p-qfjdxnhn-q.html

多了一個proactor,completion dispatcher 改成completion event queue.

流程

  1. Initiator啓動proactor.proactor內是event loop等待完成事件的到來.
  2. 有請求到來,initiator請求asy operation processor執行異步操做.異步操做完成後,將結果返回給asy operation processor.asy operation processor將結果放入到completion event queue.
  3. Proactor進行event loop,等待completion event的到來.當queue中存在completion event,proactor得到此完成事件並把事件結果傳遞給completion handler

 

 

以主動寫爲例:

  • Reactor將handle放到select(),等待可寫就緒,而後調用write()寫入數據;寫完處理後續邏輯;
  • Proactor調用aoi_write後馬上返回,由內核負責寫操做,寫完後調用相應的回調函數處理後續邏輯;
相關文章
相關標籤/搜索