大家好,我是大明哥。
上篇文章我們分析了高效能 IO模型Reactor模式,瞭解了什麼是Reactor 模式以及它的三種常見的模式,這篇文章,大明再介紹另外一種高效能IO模型: Proactor。
為什麼是 Proactor 模式
上篇文章 【死磕 NIO】— Reactor 模式就一定意味著高效能嗎?大明哥分析了 Reactor模式,我們知道Reactor效能確實非常高,適合高併發場景,但是它依然存在一個問題,那就是它是 同步IO。同步IO會有一個什麼問題呢?同步IO需要執行緒自己等待核心準備好資料,在核心準備資料的過程中,當前執行緒是阻塞的,這樣就會導致如果某個執行緒因為讀取IO的時間過長(比如讀取檔案、寫檔案),則它勢必會影響其他執行緒的執行。如果對 同步IO、 非同步IO 不瞭解的同學,可以看如下兩篇文章:
既然 同步IO有缺陷,那我們是不是可以調整為 非同步IO呢?完全可以,這就是 Proactor 模式。
什麼是 Proactor 模式
Proactor 模式整體與Reactor 模式一致,區別就在於Proactor模式將所有I/O操作都交給主執行緒和核心來處理,工作執行緒僅僅負責業務邏輯。模型如下:
-
Procator Initiator:負責建立Handler和Procator,並將Procator和Handler都通過Asynchronous operation processor註冊到核心。
-
Handler:執行業務流程的業務處理器。
-
Asynchronous operation processor:負責處理註冊請求,並完成IO操作。完成IO操作後會通知Procator。
-
Procator:根據不同的事件型別回撥不同的handler進行業務處理。
這裡需要注意的是: Proactor關注的不是就緒事件,而是完成事件,這是區分Reactor模式的關鍵點。
然而可惜的是,Linux下的非同步 I/O 是不完善的,aio
系列函式是由 POSIX
定義的非同步操作介面,不是真正的作業系統級別支援的,而是在使用者空間模擬出來的非同步,並且僅僅支援基於本地檔案的 aio
非同步操作,網路程式設計中的 socket
是不支援的,這也使得基於 Linux 的高效能網路程式都是使用 Reactor 方案。
而 Windows 裡實現了一套完整的支援 socket
的非同步程式設計介面,這套介面就是 IOCP
,是由作業系統級別實現的非同步 I/O,真正意義上非同步 I/O,因此在 Windows 裡實現高效能網路程式可以使用效率更高的 Proactor 方案。
優缺點
-
優點
- 效能確實是強大,效率也高
-
缺點
-
複雜。效能好,效率高,東西是好東西,但是使用起來就是複雜。
-
作業系統支援。上面提到過,Linux系統對非同步IO支援不是很好,不是很完善
-
Proactor 模式與Reactor 模式
Proactor模式與Reactor模式 的區別有如下幾點:
-
Reactor 模式註冊的是檔案描述符的就緒事件。當Reactor 模式有事件發生時,它需要判斷當前事件是讀事件還是寫事件,然後在呼叫系統的
read
或者write
將資料從核心中拷貝到使用者資料區,然後進行業務處理。 -
Proactor模式註冊的則是完成事件。即發起非同步操作後,作業系統將在核心態完成I/O並拷貝資料到使用者提供的緩衝區中,完成後通知Proactor進行回撥,使用者只需要處理後續的業務即可。
-
Reactor模式實現
同步I/O多路分發
-
Proactor模式實現
非同步I/O分發
。
在 Linux 作業系統下實現高併發網路程式設計依然以Reactor 模式為主。