徹底搞懂徹底搞懂事件驅動模型 - Reactor

在高性能網絡技術中,大家應該經常會看到Reactor模型。並且很多開源軟件中都使用了這個模型,如:Redis、Nginx、Memcache、Netty等。

剛開始接觸時可能一頭霧水,這到底是個什麼東東?一查英文解釋:“反應堆”,感覺更加唬人了。那麼,今天我們來一起看看這個Reactor到底是個啥。

其實通俗點講,Reacotr = IO多路複用 + 池化技術。是“大神”們將IO多路複用技術結池化技術(線程池進程池)結合的一種模式。IO多路服用負責統一監聽事件,收到事件後派發給資源池中的某個線程或進程。

其中根據Reacotr的數量和資源池中資源的數量和類型,Reactor有以下3種典型實現方案。其中“多Reactor單進程/線程”實現方案相比“單 Reactor 單進程”方案,既複雜又沒有性能優勢,因此實際沒有應用。

  1. 單Reactor + 單進程/單線程
  2. 單Reactor + 多線程
  3. 多Reactor + 多進程/多線程

下面我們逐一介紹一下這3個方案,及他們適用的場景。

單Reactor + 單進程/單線程

該方案示意圖如下(以進程舉例):

Reactor 對象通過 select 監控連接事件,收到事件後通過 dispatch 進行分發。

如果是連接建立的事件,則由 Acceptor 處理,Acceptor 通過 accept 接受連接,並創建一個 Handler 來處理連接後續的各種事件。

如果不是連接建立事件,則 Reactor 會調用連接對應的 Handler(第 2 步中創建的Handler)來進行響應。Handler 會完成 read-> 處理 ->send 的完整業務流程。

這種優點很明顯,就是簡單,不用考慮進程間通信、線程安全、資源競爭等問題。但是也有自身的侷限性,就是無法利用多核資源,只適用於業務處理非常快速的場景,Redis就是採用的這種方案。

單Reactor + 多線程

該方案示意圖如下:

與第一種方案相比,不同的是:Handler只負責響應事件,並不負責處理事件,Handler讀取數據後會發送給Processor進行處理。Processor在子線程中完成業務處理,然後將結果發送給Handler。由Handler將結果返回給client。

你可能主要到沒有列出單Reactor + 多進程方案,主要因爲如果採用多進程,就要考慮進程間通信的問題,比如子進程處理完成後需要通知父進程將結果返回給對應的client,處理比較複雜。但多線程之間數據是共享的,複雜度相對比較低。

另外,這種方案下,主線程承擔了所有的事件監聽和響應。瞬間高併發時可能會成爲性能瓶頸。這時就需要多Reactor的方案了。

多Reactor + 多進程/多線程

該方案示意圖如下(以進程舉例):

父進程中 mainReactor 對象通過 select 監控連接建立事件,收到事件後通過 Acceptor接收,將新的連接分配給某個子進程。

子進程的 subReactor 將 mainReactor 分配的連接加入連接隊列進行監聽,並創建一個Handler 用於處理連接的各種事件。

當有新的事件發生時,subReactor 會調用連接對應的 Handler(即第 2 步中創建的Handler)來進行響應。

Handler 完成 read→處理→send 的完整業務流程。

目前著名的開源系統 Nginx 採用的是多 Reactor 多進程,採用多 Reactor 多線程的實現有Memcache 和 Netty。不過需要注意的是 Nginx 中與上圖中的方案稍有差異,具體表現在主進程中並沒有mainReactor來建立連接,而是由子進程中的subReactor建立。

Proactor模式

以上就是Reactor模式中的幾種常見方案,另外除了Reactor模式還有Proactor模式。Reactor 是非阻塞同步網絡模型,因爲真正的 read 和 send 操作都需要用戶進程同步操作。這裏的“同步”指用戶進程在執行 read 和 send 這類 I/O 操作的時候是同步的,如果把 I/O 操作改爲異步就能夠進一步提升性能,這就是異步網絡模型 Proactor。

理論上 Proactor 比 Reactor 效率要高一些,但在 Linux 系統下的異步並不完善,因此在 Linux 下實現高併發網絡編程時都是以 Reactor 模式爲主。所以今天就不對 Proactor 模式進行過多介紹了。

參考資料

- https://time.geekbang.org/column/article/8805

如果以上對你有幫助,歡迎關注鐵柱,一起成長。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章