什麼是netty?
Netty是一個java開源框架.Netty提供異步的、事件驅動的網絡應用程序框架和工具,用以快速開發高性能、高可靠性的網絡服務器和客戶端程序。
也就是說,Netty 是一個基於NIO的客戶、服務器端的編程框架,使用Netty 可以確保你快速和簡單的開發出一個網絡應用,例如實現了某種協議的客戶、服務端應用。Netty相當於簡化和流線化了網絡應用的編程開發過程,例如:基於TCP和UDP的socket服務開發。
BIO模型
同步並且阻塞(傳統阻塞型),服務器實現模式爲一個連接一個線程,即客戶端有連接請求時服務端就需要啓動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷。
注:一個進程大概能開2000個左右線程
https://bbs.csdn.net/topics/360175125?list=lz
https://zhidao.baidu.com/question/1802165273358941947.html
BIO模型缺點
1.每個請求都需要創建獨立的線程,與對應的客戶端進行數據Read,業務處理,數據Write
2.當併發數較大時,需要創建大量線程來處理連接,系統資源佔用較大
3.連接建立後,如果當前線程暫時沒有數據可讀,線程就阻塞在Read操作上,造成線程資源浪費
NIO模型
1.nio有三大核心部分:Channel(管道),Buffer(緩衝區),Selector(選擇器)
2.NIO是面向緩衝區,或者面向塊編程的。數據讀取到一個它稍後處理的緩衝區,需要時可緩衝區前後移動,這就增加了處理過程中的靈活性,使用它可以提供非阻塞式的高伸縮性網絡。
Reactor
根據 Reactor 的數量和處理資源池線程的數量不同,有 3 種典型的實現
1.單 Reactor 單線程;
2.單 Reactor 多線程;
3.主從 Reactor 多線程
注:Netty 線程模式(Netty 主要基於主從 Reactor 多線程模型做了一定的改進,其中主從 Reactor 多線程模型有多個 Reactor)
reactor 單線程
1.Select 是前面 I/O 複用模型介紹的標準網絡編程 API,可以實現應用程序通過一個阻塞對象監聽多路連接請求
2.Reactor 對象通過 Select 監控客戶端請求事件,收到事件後通過 Dispatch 進行分發
3.如果是建立連接請求事件,則由 Acceptor 通過 Accept 處理連接請求,然後創建一個 Handler 對象處理連接完成後的後續業務處理
4.如果不是建立連接事件,則 Reactor 會分發調用連接對應的 Handler 來響應
5.Handler 會完成 Read→業務處理→Send 的完整業務流程
優缺點分析:
- 優點:模型簡單,沒有多線程、進程通信、競爭的問題,全部都在一個線程中完成
- 缺點:性能問題,只有一個線程,無法完全發揮多核 CPU 的性能。Handler
在處理某個連接上的業務時,整個進程無法處理其他連接事件,很容易導致性能瓶頸 - 缺點:可靠性問題,線程意外終止,或者進入死循環,會導致整個系統通信模塊不可用,不能接收和處理外部消息,造成節點故障
- 使用場景:客戶端的數量有限,業務處理非常快速,比如 Redis在業務處理的時間複雜度 O(1) 的情況
- 與之前的傳統阻塞I/O服務模型相比,服務器端用一個線程通過多路複用搞定所有的 IO 操作(包括連接,讀、寫等),編碼簡單,清晰明瞭,但是如果客戶端連接數量較多,將無法支撐。
單Reactor多線程
- Reactor 對象通過select 監控客戶端請求事件, 收到事件後,通過dispatch進行分發
- 如果建立連接請求, 則右Acceptor 通過accept 處理連接請求, 然後創建一個Handler對象處理完成連接後的各種事件
- 如果不是連接請求,則由reactor分發調用連接對應的handler 來處理
- handler 只負責響應事件,不做具體的業務處理, 通過read 讀取數據後,會分發給後面的worker線程池的某個線程處理業務
- worker 線程池會分配獨立線程完成真正的業務,並將結果返回給handler
- handler收到響應後,通過send 將結果返回給client
優缺點分析
- 優點:可以充分的利用多核cpu 的處理能力
- 缺點:多線程數據共享和訪問比較複雜, reactor 處理所有的事件的監聽和響應,在單線程運行, 在高併發場景容易出現性能瓶頸.
- 跟reactor單線程相比可以同時處理多個handler事件處理
主從Reactor 多線程
- Reactor主線程 MainReactor 對象通過select 監聽連接事件, 收到事件後,通過Acceptor 處理連接事件
- 當 Acceptor 處理連接事件後,MainReactor 將連接分配給SubReactor
- subreactor 將連接加入到連接隊列進行監聽,並創建handler進行各種事件處理
- 當有新事件發生時, subreactor 就會調用對應的handler處理
- handler 通過read 讀取數據,分發給後面的worker 線程處理
- worker 線程池分配獨立的worker 線程進行業務處理,並返回結果
- handler 收到響應的結果後,再通過send 將結果返回給client
- Reactor 主線程可以對應多個Reactor 子線程, 即MainRecator 可以關聯多個SubReactor
優缺點分析:
- 優點:父線程與子線程的數據交互簡單職責明確,父線程只需要接收新連接,子線程完成後續的業務處理。
- 優點:父線程與子線程的數據交互簡單,Reactor 主線程只需要把新連接傳給子線程,子線程無需返回數據。
- 缺點:編程複雜度較高
- 結合實例:這種模型在許多項目中廣泛使用,包括 Nginx 主從 Reactor 多進程模型,Memcached 主從多線程,Netty主從多線程模型的支持
- 與單Reactor多線程相比,它多了主Reactor和多個從屬Reactor
Netty模型
1)Netty抽象出兩組線程池 BossGroup 專門負責接收客戶端的連接, WorkerGroup 專門負責網絡的讀寫
2)BossGroup 和 WorkerGroup 類型都是 NioEventLoopGroup
3)NioEventLoopGroup 相當於一個事件循環組, 這個組中含有多個事件循環 ,每一個事件循環是 NioEventLoop
4)NioEventLoop 表示一個不斷循環的執行處理任務的線程, 每個NioEventLoop 都有一個selector , 用於監聽綁定在其上的socket的網絡通訊
5)NioEventLoopGroup 可以有多個線程, 即可以含有多個NioEventLoop
6)每個Boss NioEventLoop 循環執行的步驟有3步
- 輪詢accept 事件
- 處理accept 事件 , 與client建立連接 , 生成NioScocketChannel , 並將其註冊到某個worker NIOEventLoop 上的 selector
- 處理任務隊列的任務 , 即 runAllTasks
7)每個 Worker NIOEventLoop 循環執行的步驟
- 輪詢read, write 事件
- 處理i/o事件, 即read , write 事件,在對應NioScocketChannel 處理
- 處理任務隊列的任務 , 即 runAllTasks
8)每個Worker NIOEventLoop 處理業務時,會使用pipeline(管道), pipeline 中包含了 channel , 即通過pipeline 可以獲取到對應通道, 管道中維護了很多的 處理器
NioEventLoopGroup 下包含多個 NioEventLoop
每個 NioEventLoop 中包含有一個 Selector,一個 taskQueue
每個 NioEventLoop 的 Selector 上可以註冊監聽多個 NioChannel
每個 NioChannel 只會綁定在唯一的 NioEventLoop 上
每個 NioChannel 都綁定有一個自己的 ChannelPipeline