大家好,我是大明哥。
上篇文章我們分析了高性能 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 模式為主。