【死磕 NIO】— Proactor模式是什么?很牛逼嗎?
大家好,我是大明哥。
上篇文章我們分析了高性能 IO模型Reactor模式,了解了什么是Reactor 模式以及它的三種常見的模式,這篇文章,大明再介紹另外一種高性能IO模型:Proactor。

為什么是 Proactor 模式
上篇文章 【死磕 NIO】— Reactor 模式就一定意味著高性能嗎?大明哥分析了 Reactor模式,我們知道Reactor性能確實非常高,適合高并發(fā)場景,但是它依然存在一個問題,那就是它是 同步IO。同步IO會有一個什么問題呢?同步IO需要線程自己等待內(nèi)核準備好數(shù)據(jù),在內(nèi)核準備數(shù)據(jù)的過程中,當前線程是阻塞的,這樣就會導致如果某個線程因為讀取IO的時間過長(比如讀取文件、寫文件),則它勢必會影響其他線程的執(zhí)行。如果對 同步IO、 異步IO 不了解的同學,可以看如下兩篇文章:
【死磕NIO】— 阻塞、非阻塞、同步、異步,傻傻分不清楚
【死磕NIO】— 阻塞IO,非阻塞IO,IO復用,信號驅(qū)動IO,異步IO,這你真的分的清楚嗎?
既然 同步IO有缺陷,那我們是不是可以調(diào)整為 異步IO呢?完全可以,這就是 Proactor 模式。
什么是 Proactor 模式
Proactor 模式整體與Reactor 模式一致,區(qū)別就在于Proactor模式將所有I/O操作都交給主線程和內(nèi)核來處理,工作線程僅僅負責業(yè)務邏輯。模型如下:

Procator Initiator:負責創(chuàng)建Handler和Procator,并將Procator和Handler都通過Asynchronous operation processor注冊到內(nèi)核。
Handler:執(zhí)行業(yè)務流程的業(yè)務處理器。
Asynchronous operation processor:負責處理注冊請求,并完成IO操作。完成IO操作后會通知Procator。
Procator:根據(jù)不同的事件類型回調(diào)不同的handler進行業(yè)務處理。
這里需要注意的是:Proactor關(guān)注的不是就緒事件,而是完成事件,這是區(qū)分Reactor模式的關(guān)鍵點。
然而可惜的是,Linux下的異步 I/O 是不完善的,aio 系列函數(shù)是由 POSIX 定義的異步操作接口,不是真正的操作系統(tǒng)級別支持的,而是在用戶空間模擬出來的異步,并且僅僅支持基于本地文件的 aio 異步操作,網(wǎng)絡編程中的 socket是不支持的,這也使得基于 Linux 的高性能網(wǎng)絡程序都是使用 Reactor 方案。
而 Windows 里實現(xiàn)了一套完整的支持 socket 的異步編程接口,這套接口就是 IOCP,是由操作系統(tǒng)級別實現(xiàn)的異步 I/O,真正意義上異步 I/O,因此在 Windows 里實現(xiàn)高性能網(wǎng)絡程序可以使用效率更高的 Proactor 方案。
優(yōu)缺點
優(yōu)點
性能確實是強大,效率也高 缺點
復雜。性能好,效率高,東西是好東西,但是使用起來就是復雜。
操作系統(tǒng)支持。上面提到過,Linux系統(tǒng)對異步IO支持不是很好,不是很完善
Proactor 模式與Reactor 模式
Proactor模式與Reactor模式 的區(qū)別有如下幾點:
Reactor 模式注冊的是文件描述符的就緒事件。當Reactor 模式有事件發(fā)生時,它需要判斷當前事件是讀事件還是寫事件,然后在調(diào)用系統(tǒng)的
read或者write將數(shù)據(jù)從內(nèi)核中拷貝到用戶數(shù)據(jù)區(qū),然后進行業(yè)務處理。Proactor模式注冊的則是完成事件。即發(fā)起異步操作后,操作系統(tǒng)將在內(nèi)核態(tài)完成I/O并拷貝數(shù)據(jù)到用戶提供的緩沖區(qū)中,完成后通知Proactor進行回調(diào),用戶只需要處理后續(xù)的業(yè)務即可。
Reactor模式實現(xiàn)
同步I/O多路分發(fā)Proactor模式實現(xiàn)
異步I/O分發(fā)。
在 Linux 操作系統(tǒng)下實現(xiàn)高并發(fā)網(wǎng)絡編程依然以Reactor 模式為主。
參考資料
https://zhuanlan.zhihu.com/p/95662364
