不同的操作系統實現的io策略可能不一樣,即使是同一個操作系統也可能存在多重io策略,常見如linux上的select,poll,epoll,面對這么多不同類型的io接口,這里需要一層抽象api來完成,所以就演變出來兩種高性能的io的設計模式,分別是Reactor(同步IO)和Proactor(異步IO)。
1. Reactor
在Reactor中,事件分離器負責等待文件描述符或socket為讀寫操作準備就緒,然后將就緒事件傳遞給對應的處理器,最后由處理器負責完成實際的讀寫工作。
Reactor 的標準(典型)的工作方式是:
(1)應用程序注冊讀就緒事件和相關聯的事件處理器
(2)Reactor阻塞等待內核事件通知
(3)Reactor收到通知,然后分發可讀寫事件(讀寫準備就緒)到用戶事件處理函數
(4)用戶讀取數據,并處理數據
(5)事件處理器完成實際的讀操作,處理讀到的數據,注冊新的事件,然后返還控制權。
2. Proactor
Proactor 的標準(典型)的工作方式是:
(1)應用程序初始化一個異步讀取操作,然后注冊相應的事件處理器,此時事件處理器不關注讀取就緒事件,而是關注讀取完成事件,這是區別于Reactor的關鍵。
(2)事件分離器等待讀取操作完成事件
(3)在事件分離器等待讀取操作完成的時候,操作系統調用內核線程完成讀取操作,并將讀取的內容放入用戶傳遞過來的緩存區中。這也是區別于Reactor的一點,Proactor中,應用程序需要傳遞緩存區。
(4)事件分離器捕獲到讀取完成事件后,激活應用程序注冊的事件處理器,事件處理器直接從緩存區讀取數據,而不需要進行實際的讀取操作。
3.?簡單的理解(抄過來的)
并發系統常使用reactor模式,代替常用的多線程的處理方式,節省系統的資源,提高系統的吞吐量。
以一個餐飲為例,每一個人來就餐就是一個事件,他會先看一下菜單,然后點餐。就像一個網站會有很多的請求,要求服務器做一些事情。處理這些就餐事件的就需要我們的服務人員了。
(1) 在多線程處理的方式會是這樣的:
一個人來就餐,一個服務員去服務,然后客人會看菜單,點菜。 服務員將菜單給后廚。
二個人來就餐,二個服務員去服務……
五個人來就餐,五個服務員去服務…
?
(2) 在線程池處理的方式會是這樣的:(固定的10個人去服務,但仍然供不應求)
(3) Reactor設計模式: 單個線程來做多線程的事
? 顧客通過呼叫服務員(event事件)通知服務員,菜單寫好了,服務員就會把菜單交給廚師(事件處理器),廚師就會去做菜了。
(4) Proactor設計模式:?讓別人做完通知自己
?
?
4.?兩者的區別
區別 | Reactor | Proactor |
定義 | 被動的等待指示事件的到來,并作出反應, 它有一個等待的過程,做什么事都要放入到監聽事件集合中等待handler可用時再操作。 | 直接調用異步讀寫操作,調用完立即返回, 由內核負責寫操作,寫完后調用相應的回調函數處理后續邏輯。 |
實現 | 實現了一個被動的事件分離和分發模型 服務等待請求事件的到來,再通過不間斷地同步處理事件做出反應。 | 實現了一個主動的事件分離和分發模型。 允許多個任務并發的執行,從而提高吞吐量,可執行耗時長的任務。 |
主動與被動 | 被動 | 主動 |
同步與異步 | 同步 | 異步 |
優點 | 1.?簡單。實現相對簡單,對于耗時短的處理場景處理高效。 2.?單線程。操作系統可在多個事件源上等待。避免了多線程編程相關的性能開銷和編程復雜性。 3.?不用鎖。事件的串行化對應用時透明的,可以順序的同步執行而不需加鎖。 4.?事務隔離。將與應用無關的? ?多路分解和分配機制?與應用相關的? ?回調函數? 分離開來 | 性能更高,能夠處理耗時長的并發場景。 |
缺點 | 處理耗時長的操作會造成事務分發的阻塞,影響后續事件的處理。 | 1.?復雜。實現邏輯復雜。 2.?依賴OS對異步的支持(很少很難) |
使用場景 | 同時接受多個服務請求,并且依次同步的處理他們的事件驅動程序。 耗時短的。 | 異步接受和同時處理多個服務請求的事件驅動程序 耗時長的。 |
五.總結
基于事件驅動的網絡編程的兩種設計模式:
Reactor (反應堆?同步IO) java NIO 多路復用IO redis libevent? Linux epoll
Proactor(前攝器?異步IO) java AIO 異步IO模型 目前只有 Windows IO completion port.(iocp)模型
- 只有IOCP是asynchronous I/O,其他機制或多或少都會有一點阻塞。
- select低效是因為每次它都需要輪詢。但低效也是相對的,視情況而定,也可通過良好的設計改善
- epoll, kqueue、select是Reacor模式,IOCP是Proactor模式。
- java nio包是select模型。
- epoll, kqueue、select?等是IO策略,他們屬于設計模式,他們實現設計模式,相對于設計模式,設計策略更細節,設計模式更抽象。
摘錄網址:
I/O模型之三:兩種高性能 I/O 設計模式 Reactor 和 Proactor
IO設計模式之Reactor和Proactor
reactor和proactor模式
Reactor模式,或者叫反應器模式