【死磕 NIO】— Proactor模式是什麼?很牛逼嗎?

chenssy發表於2021-11-08

大家好,我是大明哥。

上篇文章我們分析了高效能 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 模式為主。

參考資料

相關文章