IO設計模式之Reactor和Proactor

前言

上面文章中,我們提到不同的操作系統實現的io策略可能不一樣,即使是同一個操作系統也可能存在多重io策略,常見如linux上的select,poll,epoll,面對這麼多不同類型的io接口,這裏需要一層抽象api來完成,所以就演變出來兩種高性能的io的設計模式,分別是Reactor(同步IO)和Proactor(異步IO)。

一般情況下,I/O 複用機制需要事件分享器(event demultiplexor)。 事件分離器的作用,即將那些讀寫事件源分發給各讀寫事件的處理者,就像送快遞的小哥,拉着一三輪車快遞停到了小區的快遞收發區,然後打電話通知,誰誰誰的快遞到了快來拿吧;誰誰誰要郵寄出去的快遞,快來這裏郵寄填寫表格。這裏面拿快遞就類似IO的讀請求,發快遞就類似IO的寫請求,而快遞小哥則是事件分享器,並負責完成送和收快遞的兩種事件。開發人員在開始的時候需要在分享器那裏註冊感興趣的事件,並提供相應的處理者(event handlers),或者是回調函數; 事件分享器在適當的時候會將請求的事件分發給這些handler或者回調函數。

關於Reactor

Reactor英文意思爲反應器,類似於核能的反應堆一樣,所有的能量都源源不斷從這裏傳出.或者更貼切一點叫事件的分發器。在Reactor中,事件分離器負責等待文件描述符或socket爲讀寫操作準備就緒,然後將就緒事件傳遞給對應的處理器,最後由處理器負責完成實際的讀寫工作。

Linux epoll 使用 Reactor 模式。Reactor 模式使用同步 I/O(一般來說)。Reactor 的標準(典型)的工作方式是:

(1)應用程序註冊讀就緒事件和相關聯的事件處理器

(2)Reactor阻塞等待內核事件通知

(3)Reactor收到通知,然後分發可讀寫事件(讀寫準備就緒)到用戶事件處理函數

(4)用戶讀取數據,並處理數據

(5)事件處理器完成實際的讀操作,處理讀到的數據,註冊新的事件,然後返還控制權。

這裏面需要注意,事件分離器僅僅發現當有io事件都寫就緒的時候,會通知用戶線程來讀取數據,這一步相當於io阻塞的第二個階段,從內核空間拷貝數據到用戶空間是由用戶線程完成的,所以Reactor模式實際上還屬於同步IO的模式,當然爲了架構更靈活和性能更好,一般情況下事件分離器和實際的處理器線程是分開的,類似Netty裏面的boss線程組合worker線程組一樣。

關於Proactor

Proactor英文意思前攝器,是一種異步的IO設計模式。這種模式更加理想,但真正支持純異步的io模式,目前只有windows的Windows IO completion port.(iocp)模型。

Windows iocp 使用 Praactor 模式。Praactor 模式使用異步 I/O(一般來說)。Praactor 的標準(典型)的工作方式是:

(1)應用程序初始化一個異步讀取操作,然後註冊相應的事件處理器,此時事件處理器不關注讀取就緒事件,而是關注讀取完成事件,這是區別於Reactor的關鍵。

(2)事件分離器等待讀取操作完成事件

(3)在事件分離器等待讀取操作完成的時候,操作系統調用內核線程完成讀取操作,並將讀取的內容放入用戶傳遞過來的緩存區中。這也是區別於Reactor的一點,Proactor中,應用程序需要傳遞緩存區。

(4)事件分離器捕獲到讀取完成事件後,激活應用程序註冊的事件處理器,事件處理器直接從緩存區讀取數據,而不需要進行實際的讀取操作。

從上面的描述中能夠看到,Proactor模式中,操作系統相當於直接把IO操作的兩階段工作都給幹了,這也要求應用程序在註冊異步任務時,需要傳遞一個緩存區,用來存放結果數據。這裏面事件分離器關注的是io的完成事件,而不是就緒時間,當分離器通知應用程序時,應用程序可以直接就能處理數據了。

總結

關於Reactor和Proactor這兩種IO設計模式,我們舉個實際生活中的例子:Reactor模式就是快遞員在樓下,給你打電話告訴你快遞到了,你需要自己下樓來拿快遞。而在Proactor模式下,快遞員直接將快遞送到家裏面的指定位置。

Reactor和Proactor是兩種高性能的IO設計模式,分別用於同步IO和異步IO的策略,可以看出它們都是採用的IO複用的模式,都是對某個IO事件的事件通知(即告訴某個模塊,這個IO操作可以進行或已經完成)。在結構上,兩者也有相同點:demultiplexor負責提交IO操作(異步)、查詢設備是否可操作(同步),然後當條件滿足時,就回調handler;

不同點在於,異步情況下(Proactor),當回調handler時,表示IO操作已經完成(數據已從系統內核拷貝到程序內存);同步情況下(Reactor),回調handler時,表示IO設備可以進行某個操作(can read or can write,數據準備就緒,但是用戶需要自己將數據從系統內核拷貝到程序內存)。

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