摘要:隨著狀態(tài)發(fā)生變化,相應(yīng)的產(chǎn)生。這些被轉(zhuǎn)發(fā)到中的來采取相應(yīng)的操作。當(dāng)收到數(shù)據(jù)或相關(guān)的狀態(tài)改變時(shí),這些方法被調(diào)用,這些方法和的生命周期密切相關(guān)。主要由一系列組成的。采用的線程模型,在同一個(gè)線程的中處理所有發(fā)生的事。
「博客搬家」 原地址: 簡(jiǎn)書 原發(fā)表時(shí)間: 2017-05-05
學(xué)習(xí)了一段時(shí)間的 Netty,將重點(diǎn)與學(xué)習(xí)心得總結(jié)如下,本文主要總結(jié)ChannelHandler 及 EventLoop 的知識(shí)點(diǎn)和基本用法,本文章節(jié)排序參照《Netty in Action》的章節(jié)排序。
以下內(nèi)容主要參考「并發(fā)編程網(wǎng)」的 《Netty in Action》中文版 以及《Netty in Action》原版圖書,輔助參考 Essential Netty in Action 《Netty 實(shí)戰(zhàn)(精髓)》 以及 Netty 官網(wǎng)的 Netty 4.1 JavaDoc 。6. ChannelHandler 和 ChannelPipeline
一個(gè) Channel 正常的生命周期如下圖所示。隨著狀態(tài)發(fā)生變化,相應(yīng)的 event 產(chǎn)生。這些 event 被轉(zhuǎn)發(fā)到 ChannelPipeline 中的 ChannelHandler 來采取相應(yīng)的操作。
6.1 ChannelHandlerChannelHandler 有兩個(gè)重要的子接口:
「ChannelInboundHandler」處理輸入數(shù)據(jù)和所有類型的狀態(tài)變化
「ChannelOutboundHandler」處理輸出數(shù)據(jù),可以攔截所有操作
6.1.1 ChannelInboundHandler下表列出接口 ChannelInboundHandler 的方法。當(dāng)收到數(shù)據(jù)或相關(guān) Channel 的狀態(tài)改變時(shí),這些方法被調(diào)用,這些方法和Channel的生命周期密切相關(guān)。
方法 | 描述 |
---|---|
channelRegistered | 當(dāng)一個(gè)Channel注冊(cè)到EventLoop上,可以處理I/O時(shí)被調(diào)用 |
channelUnregistered | 當(dāng)一個(gè)Channel從它的EventLoop上解除注冊(cè),不再處理I/O時(shí)被調(diào)用 |
channelActive | 當(dāng)Channel變成活躍狀態(tài)時(shí)被調(diào)用;Channel是連接/綁定、就緒的 |
channelInactive | 當(dāng)Channel離開活躍狀態(tài),不再連接到某個(gè)遠(yuǎn)端時(shí)被調(diào)用 |
channelReadComplete | 當(dāng)Channel上的某個(gè)讀操作完成時(shí)被調(diào)用 |
channelRead | 當(dāng)從Channel中讀數(shù)據(jù)時(shí)被調(diào)用 |
輸出的操作和數(shù)據(jù)由 ChannelOutBoundHandler 處理。它的方法可以被 Channel,ChannelPipeline 和 ChannelHandlerContext 調(diào)用,子接口 ChannelOutboundHandler 的主要方法如下:
方法 | 描述 |
---|---|
bind(ChannelHandlerContext,SocketAddress,ChannelPromise) | 請(qǐng)求綁定 Channel 到一個(gè)本地地址 |
connect(ChannelHandlerContext, SocketAddress,SocketAddress,ChannelPromise) | 請(qǐng)求連接 Channel 到遠(yuǎn)端 |
disconnect(ChannelHandlerContext, ChannelPromise) | 請(qǐng)求從遠(yuǎn)端斷開 Channel |
close(ChannelHandlerContext,ChannelPromise) | 請(qǐng)求關(guān)閉 Channel |
deregister(ChannelHandlerContext, ChannelPromise) | 請(qǐng)求 Channel 從它的 EventLoop 上解除注冊(cè) |
read(ChannelHandlerContext) | 請(qǐng)求從 Channel 中讀更多的數(shù)據(jù) |
flush(ChannelHandlerContext) | 請(qǐng)求通過 Channel 刷隊(duì)列數(shù)據(jù)到遠(yuǎn)端 |
write(ChannelHandlerContext,Object, ChannelPromise) | 請(qǐng)求通過 Channel 寫數(shù)據(jù)到遠(yuǎn)端 |
ChannelInboundHandlerAdapter 和 ChannelOutboundHandlerAdapter 這兩個(gè)適配器類分別提供了 ChannelInboundHandler 和 ChannelOutboundHandler 的基本實(shí)現(xiàn),它們繼承了共同的父接口 ChannelHandler 的方法,擴(kuò)展了抽象類 ChannelHandlerAdapter。
ChannelHandlerAdapter 提供了工具方法 isSharable()。如果類實(shí)現(xiàn)帶 @Sharable 注解,那么這個(gè)方法就會(huì)返回 true,意味著這個(gè)對(duì)象可以被添加到多個(gè) ChannelPipeline 中。
ChannelInboundHandlerAdapter 和 ChannelOutboundHandlerAdapter 中的方法調(diào)用相關(guān) ChannelHandlerContext 中的等效方法,因此將事件轉(zhuǎn)發(fā)到管道中的下一個(gè)ChannelHandler。
6.1.4 ChannelFuture 和 ChannelPromiseChannelPromise 是 ChannelFuture 的子接口
而 ChannelFuture 是不可變對(duì)象
ChannelPromise 定義了可寫的方法,比如 setSuccess(), setFailure()
6.1.5 釋放資源1. 輸入方向「Inbound」
當(dāng)一個(gè) ChannelInboundHandler 實(shí)現(xiàn)類重寫 channelRead() 方法時(shí),它要負(fù)責(zé)釋放 ByteBuf 相關(guān)的內(nèi)存??墒褂?Netty 提供的工具方法:
ReferenceCountUtil.release(「ByteBuf 的對(duì)象」)
更簡(jiǎn)單的,可使用子類 SimpleChannelInboundHandler ,一條消息在被 ChannelRead0() 讀取后,會(huì)被自動(dòng)釋放資源,此時(shí)任何對(duì)消息的引用都會(huì)變成無效,所以不能保存這些引用待后來使用。
2. 輸出方向「Outbound」
在輸出方向,如果處理一個(gè) write() 操作并且丟棄一條消息(沒有寫入 Channel),就應(yīng)該負(fù)責(zé)釋放這條消息。
@ChannelHandler.Sharable public class DiscardOutboundHandler extends ChannelOutboundHandlerAdapter { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { ReferenceCountUtil.release(msg); //使用 ReferenceCountUtil.release(...) 釋放資源 promise.setSuccess(); //通知 ChannelPromise 數(shù)據(jù)已經(jīng)被處理 }
如果一個(gè)消息被“消費(fèi)”或者丟棄,沒有送到 ChannelPipeline 中的下一個(gè) ChannelOutboundHandler,用戶就要負(fù)責(zé)調(diào)用 ReferenceCountUtil.release()。如果消息到達(dá)了真正的傳輸層,在它被寫到 Socket 中或者 Channel 關(guān)閉時(shí),會(huì)被自動(dòng)釋放,用戶不用管。
6.2 ChannelPipeline 接口每個(gè)新創(chuàng)建的 Channel 都會(huì)分配一個(gè)新的 ChannelPipeline,Channel 不可以更換或解除當(dāng)前的 ChannelPipeline,在 Netty 組件的整個(gè)生命周期中這個(gè)關(guān)系是固定的。
一個(gè) ChannelPipeline 可看成是一串 ChannelHandler 實(shí)例,攔截穿過 Channel 的輸入輸出 event。
根據(jù)來源,一個(gè) event 可以被一個(gè) ChannelInboundHandler 或 ChannelOutboundHandler 處理。接下來,通過調(diào)用 ChannelHandlerContext 的方法,event 會(huì)被轉(zhuǎn)發(fā)到下一個(gè)同類型的 handler。
6.2.1 ChannelHandlerContext通過 ChannelHandlerContext,一個(gè) handler 可以通知 ChannelPipeline 中的下一個(gè)ChannelHandler,甚至動(dòng)態(tài)改動(dòng)下一個(gè)ChannelHandler 所屬的 ChannelPipeline。
ChannelPipeline 主要由一系列 ChannelHandler 組成的。ChannelPipeline 提供在 ChannelPipeline 中傳送 event 的方法。
ChannelHandlerContext 的一些方法和其他類(Channel 和 ChannelPipeline)的方法名字相似,但是 ChannelHandlerContext 的方法采用了更短的 event 傳遞路程。我們應(yīng)該盡可能利用這一點(diǎn)來實(shí)現(xiàn)最好的性能。
如果你在 Channel 或者 ChannelPipeline 實(shí)例上調(diào)用這些方法,它們的調(diào)用會(huì)穿過整個(gè) pipeline。而在 ChannelHandlerContext 上調(diào)用的同樣的方法,僅僅從當(dāng)前 ChannelHandler 開始,走到 pipeline 中下一個(gè)可以處理這個(gè) event 的 ChannelHandler。
「本節(jié)參考」 第六章 ChannelHandler 和 ChannelPipeline
7. EventLoop 和 EventLoopGroup 7.1 Java 基本的線程池模式從池中空閑的線程中選出一個(gè),分配一個(gè)提交的task「一個(gè)Runnable的實(shí)現(xiàn)」
當(dāng)task完成,線程返回池中,等待復(fù)用「下一次task分配」
7.2 EventLoop「事件循環(huán)」EventLoop 始終由一個(gè)線程驅(qū)動(dòng)
一個(gè) EventLoop 可以被指派來服務(wù)多個(gè) Channel
一個(gè) Channel 只擁有一個(gè) EventLoop
task (Runnable或Callable) 可以直接提交到 EventLoop 實(shí)現(xiàn)即刻或者延后執(zhí)行。根據(jù)配置和可用的CPU核,可以創(chuàng)建多個(gè) EventLoop 來優(yōu)化資源利用。
一個(gè) event 的本質(zhì)決定了它將如何被處理;它可能從網(wǎng)絡(luò)協(xié)議棧傳送數(shù)據(jù)到你的應(yīng)用,或者反過來,或者做一些完全不一樣的事情。但是 event 處理邏輯必須足夠通用和靈活,來對(duì)付所有可能的情況。
所以,在 Netty 4,所有的 I/O 操作和 event 都是由分配給 EventLoop 的那一個(gè) Thread 來處理的。Netty 4 采用的線程模型,在同一個(gè)線程的 EventLoop 中處理所有發(fā)生的事。
7.3 EventLoopGroupEventLoopGroup 負(fù)責(zé)分配 EventLoop 到新創(chuàng)建的 Channel
異步實(shí)現(xiàn)只用了很少 EventLoop,這幾個(gè) EventLoop 被所有 Channel 共享
一但 Channel 被指派了一個(gè) EventLoop,在它的整個(gè)生命周期過程中,都會(huì)用這個(gè) EventLoop
為 Channel 的 I/O 和 event 提供服務(wù)的 EventLoop 都包含在一個(gè) EventLoopGroup 中。EventLoop 創(chuàng)建和分配的方式根據(jù)傳輸實(shí)現(xiàn)的不同而有所不同。
異步實(shí)現(xiàn)只用了很少幾個(gè) EventLoop(和它們關(guān)聯(lián)的線程),在目前 Netty 的模型中,這幾個(gè) EventLoop 被所有 Channel 共享。這讓很多 Channel 被最少數(shù)量的線程服務(wù),而不是每個(gè) Channel 分配一個(gè)線程。
EventLoopGroup 負(fù)責(zé)分配一個(gè) EventLoop 到每個(gè)新創(chuàng)建的 Channel。在目前的實(shí)現(xiàn)中,采用循環(huán) (round-robin) 策略可以滿足一個(gè)平衡的分配,同一個(gè) Eventloop 還可能會(huì)被分配到多個(gè) Channel。
「本節(jié)參考」 第七章 EventLoop和線程模型
參考鏈接《Netty in Action》中文版
Essential Netty in Action 《Netty 實(shí)戰(zhàn)(精髓)》
Netty 4.1 JavaDoc
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/68250.html
摘要:它使用了事件通知以確定在一組非阻塞套接字中有哪些已經(jīng)就緒能夠進(jìn)行相關(guān)的操作。目前,可以把看作是傳入入站或者傳出出站數(shù)據(jù)的載體。出站事件是未來將會(huì)觸發(fā)的某個(gè)動(dòng)作的操作結(jié)果,這些動(dòng)作包括打開或者關(guān)閉到遠(yuǎn)程節(jié)點(diǎn)的連接將數(shù)據(jù)寫到或者沖刷到套接字。 netty的概念 定義 Netty 是一款異步的事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用程序框架,支持快速地開發(fā)可維護(hù)的高性能的面向協(xié)議的服務(wù)器和客戶端。我們可以很簡(jiǎn)單的...
摘要:可以用來接收入站事件和數(shù)據(jù),隨后使用應(yīng)用程序的業(yè)務(wù)邏輯進(jìn)行處理。因?yàn)橛脩舨⒉皇顷P(guān)心所有的事件,因此提供了抽象類和。抽象類最常見的一個(gè)情況,你的應(yīng)用程序會(huì)利用一個(gè)來接受解碼消息,并對(duì)該數(shù)據(jù)應(yīng)用業(yè)務(wù)邏輯。 Channel、EventLoop和ChannelFuture Channel——Socket; EventLoop——控制流、多線程處理、并發(fā) ChannelFuture異步通知 ...
摘要:支持很多協(xié)議,并且提供用于數(shù)據(jù)處理的容器。我們已經(jīng)知道由特定事件觸發(fā)??蓪S糜趲缀跛械膭?dòng)作,包括將一個(gè)對(duì)象轉(zhuǎn)為字節(jié)或相反,執(zhí)行過程中拋出的異常處理。提供了一個(gè)容器給鏈并提供了一個(gè)用于管理沿著鏈入站和出站事件的流動(dòng)。子類通過進(jìn)行注冊(cè)。 前兩天寫了一點(diǎn)netty相關(guān)的知識(shí),并寫了一個(gè)demo,但是對(duì)其原理還是沒有深入,今天我們來做一次研究吧 首先讓我們來認(rèn)識(shí)一下netty的幾個(gè)核心人物吧...
摘要:在上一篇源碼實(shí)戰(zhàn)系列三全剖析中,我們?cè)敿?xì)分析了的初始化過程,并得出了如下結(jié)論在中,每一個(gè)都有一個(gè)對(duì)象,并且其內(nèi)部本質(zhì)上就是一個(gè)雙向鏈表本篇我們將深入源碼內(nèi)部,對(duì)其一探究竟,給大家一個(gè)全方位解析。 在上一篇《Netty4.x 源碼實(shí)戰(zhàn)系列(三):NioServerSocketChannel全剖析》中,我們?cè)敿?xì)分析了NioServerSocketChannel的初始化過程,并得出了如下結(jié)論...
摘要:概念與概念一致用以連接設(shè)備文件等的紐帶例如將網(wǎng)絡(luò)的讀寫客戶端發(fā)起連接主動(dòng)關(guān)閉連接鏈路關(guān)閉獲取通信雙方的網(wǎng)絡(luò)地址等的類型主要有兩種非阻塞以及阻塞數(shù)據(jù)傳輸類型有兩種按事件消息傳遞以及按字節(jié)傳遞適用方類型也有兩種服務(wù)器以及客戶端還有一些根據(jù)傳輸協(xié) ChannelHandler Channel Channel 概念與 java.nio.channel 概念一致, 用以連接IO設(shè)備 (socke...
閱讀 2814·2019-08-30 15:55
閱讀 2861·2019-08-30 15:53
閱讀 2299·2019-08-26 13:47
閱讀 2562·2019-08-26 13:43
閱讀 3161·2019-08-26 13:33
閱讀 2809·2019-08-26 11:53
閱讀 1801·2019-08-23 18:35
閱讀 804·2019-08-23 17:16