一、三種網絡IO模型:
分類:
- BIO 同步的、阻塞式 IO
- NIO 同步的、非阻塞式 IO
- AIO 異步非阻塞式 IO
阻塞和同步的概念:
- 阻塞:若讀寫未完成,調用讀寫的線程一直等待
- 非阻塞:若讀寫未完成,調用讀寫的線程不用等待,可以處理其他工作
- 異步:讀寫過程完全托管給操作系統完成,操作系統完成后通知調用讀寫的線程
- 同步:讀寫過程由本線程完成,期間可以處理其他工作,但要輪詢讀寫是否完畢
BIO 雖然可以使用線程池+等待隊列進行優化,避免使用過多的線程,但是依然無法解決線程利用率低的問題。
數據通過通道 Channel 傳輸,往Channel中讀寫數據需要先經過緩沖區Buffer
NIO為每個客戶端連接分配Channel和Buffer,並注冊到多路復用器 Selector上,Selector通過輪詢,找到有IO活動的連接進行處理,這種處理模式稱為Reactor模式
若當前通道無可用數據,線程不會阻塞,而是可以處理其他通道的讀寫
這樣 降低了線程的需求量,提高了線程的利用率 實現了IO 多路復用
IO 多路復用的定義:單個線程 管理多個IO流
二、Reactor模式
Reactor模式基本原理是
1)Reactor:Reactor 在一個單獨的線程中運行,負責監聽和分發多個客戶端的事件,分發給適當的handler線程來對 IO 事件做出反應。
2)Handlers:處理線程 會執行處理方法來 響應 I/O 事件
Reactor 模式就是實現網絡 IO 程序高並發特性的關鍵。
它又可以分為單 Reactor 單線程模式、單 Reactor 多線程模式、主從 Reactor 多線程模式。
這種模式的基本工作流程為:
1)Reactor 通過 select 監聽客戶端請求事件,收到事件之后通過 dispatch 進行分發
2)若事件是建立連接的請求,則由 Acceptor 通過 accept 處理連接請求,然后創建一個 Handler 對象處理連接建立后的后續業務。
3)若不是建立連接的請求,則分發給此連接對應的 Handler 處理。
4)Handler 會完成 read-->業務處理-->send 的完整處理流程。
簡單來說就是:一個線程 處理多個連接的請求、分發、read,send、業務處理 操作
優點是:模型簡單,沒有多線程、進程通信、競爭的問題,一個線程完成所有的事件響應和業務處理。
缺點是:
1)存在性能問題,只有一個線程,無法完全發揮多核 CPU 的性能。Handler 在處理某個連接上的業務時,整個進程無法處理其他連接事件,很容易導致性能瓶頸。
2)存在可靠性問題,若線程意外終止,或者進入死循環,會導致整個系統通信模塊不可用,不能接收和處理外部消息,造成節點故障。
使用場景為:客戶端的數量有限,業務處理非常快速,比如 Redis // 在業務處理的時間復雜度為 O(1)的情況。
單 Reactor 多線程模式 使用了
一個Reactor主線程 處理 多個客戶端的 監聽 連接 分發 read和send
多個Worker線程 處理多個客戶端的業務
這種模式的優點是可以充分的利用多核 CPU的處理能力,
缺點是多線程數據共享和控制比較復雜,Reactor 處理所有的事件的監聽和響應,在單線程中運行,面對高並發場景還是容易出現性能瓶頸。
主從 Reactor 多線程模式 使用了
一個Reactor主線程 處理 多個客戶端的監聽,連接,分發
多個Reactor子線程處理多個客戶端的 read和send
多個Worker線程 處理多個客戶端的業務
MainReactor 只負責監聽客戶端連接請求,和客戶端建立連接之后將連接交由 SubReactor 監聽后面的 IO 事件。
這種模式的優點是:
1)MainReactor 線程與 SubReactor 線程職責明確,MainReactor 線程只需要接收新連接,SubReactor 線程完成后續的業務處理。
2)交互簡單, MainReactor 線程只需要把新連接傳給 SubReactor 線程,由SubReactor 返回數據給客戶端
3)多個 SubReactor 線程能夠應對更高的並發請求。
這種模式的缺點是編程復雜度較高。但是由於其優點明顯,在許多項目中被廣泛使用,包括 Nginx、Memcached、Netty 等。
這種模式也被叫做服務器的 1+M+N 線程模式,即使用該模式開發的服務器包含一個(或多個,1 只是表示相對較少)連接建立線程+M 個 IO 線程+N 個業務處理線程。這是業界成熟的服務器程序設計模式。