netty 學習(一)
Netty學習
Netty元件
Channel
在Netty中Channel可以抽象為,一個socket連線,根據不同的型別,可以有
- EmbeddedChannel;
- LocalServerChannel;
- NioDatagramChannel;
- NioSctpChannel;
- NioSocketChannel
這些channel
把這些channel看成一個個個體,而不是概念。
NioEventLoop
NioEventLoopGroup相當於起了兩個執行緒,一個是監聽客戶端連線(boss),另一個是處理客戶端讀寫(worker)。
第二個NioEventLoopGroup中的一個EventLoop來處理這個Channel上的所有讀寫事件。一個Channel只會被一個EventLoop處理,而一個EventLoop可能會被分配給多個Channel。
- 一個EventLoopGroup包含一個或者多個EventLoop;
- 一個EventLoop在它的生命週期內只和一個Thread繫結;
- 所有由EventLoop處理的 I/O 事件都將在它專有的Thread上被處理;
- 一個Channel在它的生命週期內只註冊於一個EventLoop;
- 一個EventLoop可能會被分配給一個或多個Channel。
注意,在這種設計中,一個給定Channel的 I/O 操作都是由相同的Thread執行的,實際 上消除了對於同步的需要。
ChannelPipeline和ChannelHandler和ChannelContext
ChannelPipeline對應邏輯鏈,也就是logic chain,這個邏輯鏈說白了就是我們需要對所有傳輸資料的邏輯處理,ChannelHandler就是一個邏輯處理(logic),由n個ChannelHandler組成ChannelPipeline。
Netty使用類似責任鏈的模式來設計ChannelPipeline和ChannelHandler
ChannelPipeline相當於ChannelHandler的容器,channel事件訊息在ChannelPipeline中流動和傳播,相應的事件能夠被ChannelHandler攔截處理、傳遞、忽略或者終止。
每個ChannelHandler 被新增到ChannelPipeline 後,都會建立一個ChannelHandlerContext 並與之建立的ChannelHandler 關聯繫結。
ChannelFuture
正如我們已經解釋過的那樣,Netty 中所有的 I/O 操作都是非同步的。因為一個操作可能不會 立即返回,所以我們需要一種用於在之後的某個時間點確定其結果的方法。為此,Netty 提供了 ChannelFuture介面,其addListener()方法註冊了一個ChannelFutureListener,以 便在某個操作完成時(無論是否成功)得到通知。
底層模型
NIO 模型基礎
幾個概念:
- 非阻塞
- Channel
- Buffer
- Selector
- 註冊感興趣事件
reactor 模型基礎
首先要需要說明的是,reactor執行緒模型並不是netty所獨有,其是一種併發程式設計模型,更確切的或者說一種思想,其具有的是指導意義,開發者需要在這種程式設計模型思想的指導下,結合自己的實際場景,來進行合理的設計。換句話說,netty只是結合了nio網路程式設計的特點,合理的應用了reactor執行緒模型。關於netty是如何合理的利用reactor執行緒模型,將在之後講解。
單執行緒模型
單個執行緒以非阻塞IO或事件IO處理所有IO事件,包括連線、讀、寫、異常、關閉等等。單執行緒Reactor模型基於同步事件分離器來分發事件,這個同步事件分離器,可以看做是一個單執行緒的while迴圈。下圖描述了單執行緒模型的處理過程,看起來與網上大部分資料的圖片不同,但本質是相同的。
多執行緒模型
一個執行緒/程序接收連線、一組執行緒/程序處理IO讀寫事件。也就是將accept的執行緒與處理讀、寫等IO事件的執行緒分離,並且使用m多個執行緒、使用非阻塞IO或者事件IO來處理n個套接字的IO事件,這裡的n一般遠大於m,m一般取CPU邏輯核心數的1-3倍,而套接字數n則取決於請求數和程序可以開啟的最大描述符個數。
主從多執行緒模型
一組執行緒/程序接收連線、一組執行緒/程序處理IO讀寫事件。它與多執行緒模型的主要區別在於其使用一組執行緒或程序在一個共享的監聽套接字上accept連線。這麼做的原因是為了應付單個執行緒/程序不足以快速處理核心中監聽套接字的已連線套接字佇列(併發量極大)的情況。