一、組件

- 一個(gè) EventLoopGroup 包含一個(gè)或者多個(gè) EventLoop ;
- 一個(gè) EventLoop 在它的生命周期內(nèi)只和一個(gè) Thread 綁定;
- 所有由 EventLoop 處理的 I/O 事件都將在它專有的 Thread 上被處理;
- 一個(gè) Channel 在它的生命周期內(nèi)只注冊(cè)于一個(gè) EventLoop ;
- 一個(gè) EventLoop 可能會(huì)被分配給一個(gè)或多個(gè) Channel 。
二、其他
Netty中所有的 I/O 操作都是異步的。一個(gè)操作可能不會(huì)立即返回,所以我們需要一種用于在之后的某個(gè)時(shí)間點(diǎn)確定其結(jié)果的方法。為此,Netty提供了ChannelFuture接口,其 addListener() 方法注冊(cè)了一個(gè) ChannelFutureListener ,以便在某個(gè)操作完成時(shí)(無(wú)論是否成功)得到通知。
可以將 ChannelFuture 看作是將來(lái)要執(zhí)行的操作的結(jié)果的占位符。它究竟什么時(shí)候被執(zhí)行則可能取決于若干的因素,因此不可能準(zhǔn)確地預(yù)測(cè),但是它一定會(huì)被執(zhí)行。此外,所有屬于同一個(gè) Channel 的操作都被保證其將以它們被調(diào)用的順序被執(zhí)行。
-
, ChannelHandler它充當(dāng)了所有
處理入站和出站數(shù)據(jù)的應(yīng)用程序邏輯的容器。 可專門(mén)用于幾乎任何類(lèi)型的動(dòng)作,例如將數(shù)據(jù)從一種格式轉(zhuǎn)換為另外一種格式,或者處理轉(zhuǎn)換過(guò)程中所拋出的異常。
業(yè)務(wù)邏輯通常駐留在一個(gè)或者多個(gè) ChannelInboundHandler 中。
ChannelHandler結(jié)構(gòu).png ChannelPipeline 提供了 ChannelHandler 鏈的容器,并定義了用于在該鏈上傳播入站和出站事件流的 API。當(dāng) Channel 被創(chuàng)建時(shí),它會(huì)被自動(dòng)地分配到它專屬的 ChannelPipeline 。
ChannelHandler 安裝到 ChannelPipeline 中的過(guò)程:
(1) 一個(gè) ChannelInitializer 的實(shí)現(xiàn)被注冊(cè)到了 ServerBootstrap 中
(2) 當(dāng) ChannelInitializer.initChannel() 方法被調(diào)用時(shí), ChannelInitializer將在 ChannelPipeline 中安裝一組自定義的 ChannelHandler ;
(3)ChannelInitializer將它自己從 ChannelPipeline 中移除。
使得事件流經(jīng) ChannelPipeline 是 ChannelHandler 的工作,它們是在應(yīng)用程序的初始化或者引導(dǎo)階段被安裝的。這些對(duì)象接收事件、執(zhí)行它們所實(shí)現(xiàn)的處理邏輯,并將數(shù)據(jù)傳遞給鏈中的下一個(gè) ChannelHandler 。它們的執(zhí)行順序是由它們被添加的順序所決定的。
事件的運(yùn)動(dòng)方向是從客戶端到服務(wù)器端,那么我們稱這些事件為出站的,反之則稱為入站的。
在 Netty 中,有兩種發(fā)送消息的方式。你可以直接寫(xiě)到 Channel 中,也可以寫(xiě)到和 ChannelHandler 相關(guān)聯(lián)的 ChannelHandlerContext 對(duì)象中。前一種方式將會(huì)導(dǎo)致消息從 ChannelPipeline 的尾端開(kāi)始流動(dòng),而后者將導(dǎo)致消息從 ChannelPipeline 中的下一個(gè) ChannelHandler 開(kāi)始流動(dòng)。
適配器:ChannelHandlerAdapter、 ChannelInboundHandlerAdapter、ChannelOutboundHandlerAdapter
SimpleChannelInboundHandler
-
有 兩 種 類(lèi) 型 的 引 導(dǎo) : 一 種 用 于 客 戶 端 ( 簡(jiǎn) 單 地 稱 為 Bootstrap ), 而 另 一種( ServerBootstrap )用于服務(wù)器。無(wú)論你的應(yīng)用程序使用哪種協(xié)議或者處理哪種類(lèi)型的數(shù)據(jù),唯一決定它使用哪種引導(dǎo)類(lèi)的是它是作為一個(gè)客戶端還是作為一個(gè)服務(wù)器。
比較.png
服務(wù)器需要兩組不同的 Channel 。第一組將只包含一個(gè) ServerChannel ,代表服務(wù)器自身的已綁定到某個(gè)本地端口的正在監(jiān)聽(tīng)的套接字。而第二組將包含所有已創(chuàng)建的用來(lái)處理傳入客戶端連接(對(duì)于每個(gè)服務(wù)器已經(jīng)接受的連接都有一個(gè))的 Channel 。


三、組件
-
Channel 的正常生命周期狀態(tài)發(fā)生改變時(shí),將會(huì)生成對(duì)應(yīng)的事件。這些事件將會(huì)被轉(zhuǎn)發(fā)給 ChannelPipeline 中的 ChannelHandler ,其可以隨后對(duì)它們做出響應(yīng)。
channel生命周期狀態(tài).png
-
在 ChannelHandler被添加到 ChannelPipeline 中或者被從 ChannelPipeline 中移除時(shí)會(huì)調(diào)用這些操作。這些方法中的每一個(gè)都接受一個(gè) ChannelHandlerContext 參數(shù)。
ChannelHander生命周期.png -
ChannelInboundHandler ——處理入站數(shù)據(jù)以及各種狀態(tài)變化;
這些方法將會(huì)在數(shù)據(jù)被接收時(shí)或者與其對(duì)應(yīng)的 Channel 狀態(tài)發(fā)生改變時(shí)被調(diào)用。
ChannelInboundHandler方法.png
-
ChannelOutboundHandler ——處理出站數(shù)據(jù)并且允許攔截所有的操作。
ChannelOutboundHandler 的一個(gè)強(qiáng)大的功能是可以按需推遲操作或者事件,這使得可以通過(guò)一些復(fù)雜的方法來(lái)處理請(qǐng)求。
ChannelOutboundHandler方法.png
ChannelOutboundHandler 中的大部分方法都需要一個(gè)ChannelPromise 參數(shù),以便在操作完成時(shí)得到通知。 ChannelPromise 是 ChannelFuture 的一個(gè)子類(lèi),其定義了一些可寫(xiě)的方法,如 setSuccess() 和 setFailure() ,從而使 ChannelFuture 不可變 。
每一個(gè)新創(chuàng)建的 Channel 都將會(huì)被分配一個(gè)新的 ChannelPipeline 。這項(xiàng)關(guān)聯(lián)是永久性的;
通常 ChannelPipeline 中的每一個(gè) ChannelHandler 都是通過(guò)它的 EventLoop (I/O 線程)來(lái)處理傳遞給它的事件的。
(1)ChannelPipeline 保存了與 Channel 相關(guān)聯(lián)的 ChannelHandler ;
(2)ChannelPipeline 可以根據(jù)需要,通過(guò)添加或者刪除 ChannelHandler 來(lái)動(dòng)態(tài)地修改;
(3)ChannelPipeline 有著豐富的 API 用以被調(diào)用,以響應(yīng)入站和出站事件。ChannelHandlerContext 代表了 ChannelHandler 和 ChannelPipeline 之間的關(guān)
聯(lián),每當(dāng)有 ChannelHandler 添加到 ChannelPipeline 中時(shí),都會(huì)創(chuàng)建ChannelHandlerContext 。 ChannelHandlerContext 的主要功能是管理它所關(guān)聯(lián)的 ChannelHandler 和在同一個(gè) ChannelPipeline 中的其他 ChannelHandler 之間的交互。ChannelHandler 可 以 通 知 其 所 屬 的 ChannelPipeline 中 的 下 一 個(gè)ChannelHandler ,甚至可以動(dòng)態(tài)修改它所屬的 ChannelPipeline 。
ChannelHandlerContext 和 ChannelHandler 之間的關(guān)聯(lián)(綁定)是永遠(yuǎn)不會(huì)改
變的,所以緩存對(duì)它的引用是安全的;
相對(duì)于其他類(lèi)的同名方法, ChannelHandlerContext的方法將產(chǎn)生更短的事件流,應(yīng)該盡可能地利用這個(gè)特性來(lái)獲得最大的性能。
因?yàn)橐粋€(gè) ChannelHandler 可以從屬于多個(gè) ChannelPipeline ,所以它也可以綁定到多個(gè) ChannelHandlerContext 實(shí)例。對(duì)于這種用法指在多個(gè) ChannelPipeline 中共享同一個(gè) ChannelHandler ,對(duì)應(yīng)的 ChannelHandler 必須要使用 @Sharable 注解標(biāo)注;否則,試圖將它添加到多個(gè) ChannelPipeline 時(shí)將會(huì)觸發(fā)異常。
只應(yīng)該在確定了你的 ChannelHandler 是線程安全的時(shí)才使用 @Sharable 注解。
在多個(gè) ChannelPipeline 中安裝同一個(gè) ChannelHandler的一個(gè)常見(jiàn)的原因是用于收集跨越多個(gè) Channel 的統(tǒng)計(jì)信息。

四、異常
入站異常處理
ChannelHandler.exceptionCaught() 的默認(rèn)實(shí)現(xiàn)是簡(jiǎn)單地將當(dāng)前異常轉(zhuǎn)發(fā)給ChannelPipeline 中的下一個(gè) ChannelHandler ;如果異常到達(dá)了 ChannelPipeline 的尾端,它將會(huì)被記錄為未被處理;
要想定義自定義的處理邏輯,你需要重寫(xiě) exceptionCaught() 方法。然后你需要決定是否需要將該異常傳播出去。出站異常
每個(gè)出站操作都將返回一個(gè) ChannelFuture 。注冊(cè)到 ChannelFuture 的 Channel-
FutureListener 將在操作完成時(shí)被通知該操作是成功了還是出錯(cuò)了。
幾乎所有的 ChannelOutboundHandler 上的方法都會(huì)傳入一個(gè) ChannelPromise
的實(shí)例。作為 ChannelFuture 的子類(lèi), ChannelPromise 也可以被分配用于異步通
知的監(jiān)聽(tīng)器。但是, ChannelPromise 還具有提供立即通知的可寫(xiě)方法:
ChannelPromise setSuccess()、ChannelPromise setFailure(Throwable cause);





