-
只更新在筆者的知識星球,歡迎加入一起討論 Netty 原始碼與實現。
-
目前已經有 1000+ 位球友加入…
-
進度:已經完成 60+ 篇,預計總共 70+ 篇,完成度 90% 。
-
對應 Netty 版本號:4.1.26.Final
1.1 目錄
-
除錯環境搭建
-
《精盡 Netty 原始碼分析 —— 除錯環境搭建》
-
NIO 基礎
-
《精盡 Netty 原始碼分析 —— NIO 基礎(一)之簡介》
-
《精盡 Netty 原始碼分析 —— NIO 基礎(二)之 Channel》
-
《精盡 Netty 原始碼分析 —— NIO 基礎(三)之 Buffer》
-
《精盡 Netty 原始碼分析 —— NIO 基礎(四)之 Selector》
-
《精盡 Netty 原始碼分析 —— NIO 基礎(五)之示例》
-
Netty 簡介
-
《精盡 Netty 原始碼分析 —— Netty 簡介(一)之專案結構》
-
《精盡 Netty 原始碼分析 —— Netty 簡介(二)之核心元件》
-
啟動
-
《精盡 Netty 原始碼分析 —— 啟動(一)之服務端啟動》
-
《精盡 Netty 原始碼分析 —— 啟動(二)之客戶端啟動》
-
EventLoop
-
《精盡 Netty 原始碼解析 —— EventLoop(一)之 Reactor 模型》
-
《精盡 Netty 原始碼解析 —— EventLoop(二)之 EventLoopGroup》
-
《精盡 Netty 原始碼解析 —— EventLoop(三)之 EventLoop 初始化》
-
《精盡 Netty 原始碼解析 —— EventLoop(四)之 EventLoop 執行》
-
《精盡 Netty 原始碼解析 —— EventLoop(五)之 EventLoop 處理 IO 事件》
-
《精盡 Netty 原始碼解析 —— EventLoop(六)之 EventLoop 處理普通任務》
-
《精盡 Netty 原始碼解析 —— EventLoop(七)之 EventLoop 處理定時任務》
-
《精盡 Netty 原始碼解析 —— EventLoop(八)之 EventLoop 優雅關閉》
-
ChannelPipeline
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(一)之初始化》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(二)之新增 ChannelHandler》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(三)之刪除 ChannelHandler》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(四)之 OutBound 事件的傳播》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(五)之 Inbound 事件的傳播》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(六)之異常的傳播》
-
Channel
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(一)之簡介》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(二)之 accept 操作》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(三)之 read 操作》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(四)之 write 操作》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(五)之 flush 操作》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(六)之 writeAndFlush 操作》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(七)之 close 操作》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(八)之 disconnect 操作》
-
Bytebuf
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBuf(一)簡介》
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBuff(二)核心子類》
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBuff(三)記憶體洩露檢測》
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBuff(四)其它子類》
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBufAllocator(一)簡介》
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBufAllocator(二)UnpooledByteBufAllocator》
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBufAllocator(三)PooledByteBufAllocator》
-
《精盡 Netty 原始碼解析 —— Buffer 之 Jemalloc(一)簡介》
-
《精盡 Netty 原始碼解析 —— Buffer 之 Jemalloc(二)PoolChunk》
-
《精盡 Netty 原始碼解析 —— Buffer 之 Jemalloc(三)PoolSubpage》
-
《精盡 Netty 原始碼解析 —— Buffer 之 Jemalloc(四)PoolChunkList》
-
《精盡 Netty 原始碼解析 —— Buffer 之 Jemalloc(五)PoolArena》
-
《精盡 Netty 原始碼解析 —— Buffer 之 Jemalloc(六)PoolThreadCache》
-
ChannelHandler
-
《精盡 Netty 原始碼解析 —— ChannelHandler(一)之簡介》
-
《精盡 Netty 原始碼解析 —— ChannelHandler(二)之 ChannelInitializer》
-
《精盡 Netty 原始碼解析 —— ChannelHandler(三)之 SimpleChannelInboundHandler》
-
《精盡 Netty 原始碼解析 —— ChannelHandler(四)之 LoggingHandler》
-
《精盡 Netty 原始碼解析 —— ChannelHandler(五)之 IdleStateHandler》
-
《精盡 Netty 原始碼解析 —— ChannelHandler(六)之 AbstractTrafficShapingHandler》
-
Codec
-
《精盡 Netty 原始碼解析 —— Codec 之 ByteToMessageDecoder(一)Cumulator》
-
《精盡 Netty 原始碼解析 —— Codec 之 ByteToMessageDecoder(二)FrameDecoder》
-
《精盡 Netty 原始碼解析 —— Codec 之 MessageToByteEncoder》
-
《精盡 Netty 原始碼解析 —— Codec 之 ByteToMessageCodec》
-
《精盡 Netty 原始碼解析 —— Codec 之 MessageToMessageCodec》
-
Util
-
《精盡 Netty 原始碼解析 —— Util 之 Future》
-
《精盡 Netty 原始碼解析 —— Util 之 FastThreadLocal》
-
《精盡 Netty 原始碼解析 —— Util 之 Recycler》
-
《精盡 Netty 原始碼解析 —— Util 之 HashedWheelTimer》
-
《精盡 Netty 原始碼解析 —— Util 之 MpscUnboundedArrayQueue》
1.2 Netty 實現原理淺析
本小節基於 《Netty 實現原理淺析》 重新整理。
透過讀《Netty 實現原理淺析》,對 Netty 原理有基本的認知。
透過讀《精盡 Netty 原始碼解析》,對 Netty 原理有深入的理解。
另外,《Netty 實現原理淺析》 是基於 Netty3 版本寫的,所以和現在 Netty4 版本有一些不同。
而 《精盡 Netty 原始碼》 是基於 Netty4 最新版本寫的。
? 可能有胖友說,Netty5 版本才是最新的。但是實際上,這個版本已經被官方廢棄。目前主流的中介軟體,例如 Dubbo、RocketMQ、Motan、SOFA-RPC 等等,都是基於 Netty4 來實現網路通訊功能。
Netty 是 JBoss 出品的高效的 Java NIO 開發框架,關於其使用,可參考我的另一篇文章 《netty 使用初步》 。
本文將主要分析 Netty 實現方面的東西,由於精力有限,本人並沒有對其原始碼做了極細緻的研究。如果下麵的內容有錯誤或不嚴謹的地方,也請指正和諒解。對於 Netty 使用者來說,Netty 提供了幾個典型的 example ,並有詳盡的 API doc 和 guide doc ,本文的一些內容及圖示也來自於 Netty 的檔案,特此致謝。
1.2.1 總體結構
先放上一張漂亮的 Netty 總體結構圖,下麵的內容也主要圍繞該圖上的一些核心功能做分析,但對如 Container Integration 及 Security Support 等高階可選功能,本文不予分析。
對應原始碼解析文章:
-
《精盡 Netty 原始碼分析 —— Netty 簡介(一)之專案結構》
-
《精盡 Netty 原始碼分析 —— Netty 簡介(二)之核心元件》
1.2.2 網路模型
Netty 是典型的 Reactor 模型結構,關於 Reactor 的詳盡闡釋,可參考 POSA2 ,這裡不做概念性的解釋。而應用 Java NIO 構建 Reactor 樣式,Doug Lea(就是那位讓人無限景仰的大爺)在 “Scalable IO in Java” 中給了很好的闡述。這裡擷取其 PPT 中經典的圖例說明 Reactor 樣式的典型實現:
1、這是最簡單的單 Reactor 單執行緒模型。Reactor 執行緒是個多面手,負責多路分離套接字,Accept 新連線,並分派請求到處理器鏈中。該模型 適用於處理器鏈中業務處理元件能快速完成的場景。不過,這種單執行緒模型不能充分利用多核資源,所以實際使用的不多。
2、相比上一種模型,該模型在處理器鏈部分採用了多執行緒(執行緒池),也是後端程式常用的模型。
3、 第三種模型比起第二種模型,是將 Reactor 分成兩部分,mainReactor 負責監聽 server socket,accept 新連線,並將建立的 socket 分派給 subReactor 。subReactor 負責多路分離已連線的socket,讀寫網路資料,對業務處理功能,其扔給 worker 執行緒池完成。通常,subReactor 個數上可與 CPU個 數等同。
說完 Reactor 模型的三種形式,那麼Netty是哪種呢?其實,我還有一種Reactor模型的變種沒說,那就是去掉執行緒池的第三種形式的變種,這也 是Netty NIO的預設樣式。在實現上,Netty中的Boss類充當mainReactor,NioWorker 類充當subReactor(預設 NioWorker 的個數是Runtime.getRuntime().availableProcessors())。在處理新來的請求 時,NioWorker 讀完已收到的資料到 ChannelBuffer 中,之後觸發ChannelPipeline 中的 ChannelHandler 流。
Netty是事件驅動的,可以透過ChannelHandler鏈來控制執行流向。因為ChannelHandler鏈的執行過程是在 subReactor中同步的,所以如果業務處理handler耗時長,將嚴重影響可支援的併發數。這種模型適合於像Memcache這樣的應用場景,但 對需要運算元據庫或者和其他模組阻塞互動的系統就不是很合適。Netty的可擴充套件性非常好,而像ChannelHandler執行緒池化的需要,可以透過在 ChannelPipeline中新增Netty內建的ChannelHandler實現類–ExecutionHandler實現,對使用者來說只是 新增一行程式碼而已。對於ExecutionHandler需要的執行緒池模型,Netty提供了兩種可 選:1) MemoryAwareThreadPoolExecutor 可控制Executor中待處理任務的上限(超過上限時,後續進來的任務將被阻 塞),並可控制單個Channel待處理任務的上限;2) OrderedMemoryAwareThreadPoolExecutor 是 MemoryAwareThreadPoolExecutor 的子類,它還可以保證同一Channel中處理的事件流的順序性,這主要是控制事件在非同步處 理樣式下可能出現的錯誤的事件順序,但它並不保證同一Channel中的事件都在一個執行緒中執行(通常也沒必要)。一般來 說,OrderedMemoryAwareThreadPoolExecutor 是個很不錯的選擇,當然,如果有需要,也可以DIY一個。
對應原始碼解析文章:
-
《精盡 Netty 原始碼解析 —— EventLoop(一)之 Reactor 模型》
-
《精盡 Netty 原始碼解析 —— EventLoop(二)之 EventLoopGroup》
-
《精盡 Netty 原始碼解析 —— EventLoop(三)之 EventLoop 初始化》
-
《精盡 Netty 原始碼解析 —— EventLoop(四)之 EventLoop 執行》
-
《精盡 Netty 原始碼解析 —— EventLoop(五)之 EventLoop 處理 IO 事件》
-
《精盡 Netty 原始碼解析 —— EventLoop(六)之 EventLoop 處理普通任務》
-
《精盡 Netty 原始碼解析 —— EventLoop(七)之 EventLoop 處理定時任務》
-
《精盡 Netty 原始碼解析 —— EventLoop(八)之 EventLoop 優雅關閉》
1.2.3 buffer
org.jboss.netty.buffer
包的介面及類的結構圖如下:該包核心的介面是ChannelBuffer和ChannelBufferFactory,下麵予以簡要的介紹。
Netty使用ChannelBuffer來儲存並操作讀寫的網路資料。ChannelBuffer除了提供和ByteBuffer類似的方法,還提供了 一些實用方法,具體可參考其API檔案。ChannelBuffer的實現類有多個,這裡列舉其中主要的幾個:
1)HeapChannelBuffer:這是Netty讀網路資料時預設使用的ChannelBuffer,這裡的Heap就是Java堆的意思,因為 讀SocketChannel的資料是要經過ByteBuffer的,而ByteBuffer實際操作的就是個byte陣列,所以 ChannelBuffer的內部就包含了一個byte陣列,使得ByteBuffer和ChannelBuffer之間的轉換是零複製方式。根據網路字 節續的不同,HeapChannelBuffer又分為BigEndianHeapChannelBuffer和 LittleEndianHeapChannelBuffer,預設使用的是BigEndianHeapChannelBuffer。Netty在讀網路 資料時使用的就是HeapChannelBuffer,HeapChannelBuffer是個大小固定的buffer,為了不至於分配的Buffer的 大小不太合適,Netty在分配Buffer時會參考上次請求需要的大小。
2)DynamicChannelBuffer:相比於HeapChannelBuffer,DynamicChannelBuffer可動態自適應大 小。對於在DecodeHandler中的寫資料操作,在資料大小未知的情況下,通常使用DynamicChannelBuffer。
3)ByteBufferBackedChannelBuffer:這是directBuffer,直接封裝了ByteBuffer的 directBuffer。
對於讀寫網路資料的buffer,分配策略有兩種:1)通常出於簡單考慮,直接分配固定大小的buffer,缺點是,對一些應用來說這個大小限制有時是不 合理的,並且如果buffer的上限很大也會有記憶體上的浪費。2)針對固定大小的buffer缺點,就引入動態buffer,動態buffer之於固定 buffer相當於List之於Array。
buffer的寄存策略常見的也有兩種(其實是我知道的就限於此):1)在多執行緒(執行緒池) 模型下,每個執行緒維護自己的讀寫buffer,每次處理新的請求前清空buffer(或者在處理結束後清空),該請求的讀寫操作都需要在該執行緒中完成。 2)buffer和socket系結而與執行緒無關。兩種方法的目的都是為了重用buffer。
Netty對buffer的處理策略是:讀請求資料時,Netty首先讀資料到新建立的固定大小的HeapChannelBuffer中,當HeapChannelBuffer滿或者沒有資料可讀 時,呼叫handler來處理資料,這通常首先觸發的是使用者自定義的DecodeHandler,因為handler物件是和ChannelSocket 系結的,所以在DecodeHandler裡可以設定ChannelBuffer成員,當解析資料包發現資料不完整時就終止此次處理流程,等下次讀事件觸 發時接著上次的資料繼續解析。就這個過程來說,和ChannelSocket系結的DecodeHandler中的Buffer通常是動態的可重用 Buffer(DynamicChannelBuffer),而在NioWorker中讀ChannelSocket中的資料的buffer是臨時分配的 固定大小的HeapChannelBuffer,這個轉換過程是有個位元組複製行為的。
對ChannelBuffer的建立,Netty內部使用的是ChannelBufferFactory介面,具體的實現有 DirectChannelBufferFactory和HeapChannelBufferFactory。對於開發者建立 ChannelBuffer,可使用實用類ChannelBuffers中的工廠方法。
對應原始碼解析文章:
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBuf(一)簡介》
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBuff(二)核心子類》
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBuff(三)記憶體洩露檢測》
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBuff(四)其它子類》
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBufAllocator(一)簡介》
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBufAllocator(二)UnpooledByteBufAllocator》
-
《精盡 Netty 原始碼解析 —— Buffer 之 ByteBufAllocator(三)PooledByteBufAllocator》
-
《精盡 Netty 原始碼解析 —— Buffer 之 Jemalloc(一)簡介》
-
《精盡 Netty 原始碼解析 —— Buffer 之 Jemalloc(二)PoolChunk》
-
《精盡 Netty 原始碼解析 —— Buffer 之 Jemalloc(三)PoolSubpage》
-
《精盡 Netty 原始碼解析 —— Buffer 之 Jemalloc(四)PoolChunkList》
-
《精盡 Netty 原始碼解析 —— Buffer 之 Jemalloc(五)PoolArena》
-
《精盡 Netty 原始碼解析 —— Buffer 之 Jemalloc(六)PoolThreadCache》
1.2.4 Channel
和Channel相關的介面及類結構圖如下:
從該結構圖也可以看到,Channel主要提供的功能如下:
1)當前Channel的狀態資訊,比如是開啟還是關閉等。
2)透過ChannelConfig可以得到的Channel配置資訊。
3)Channel所支援的如read、write、bind、connect等IO操作。
4)得到處理該Channel的ChannelPipeline,既而可以呼叫其做和請求相關的IO操作。在Channel實現方面,以通常使用的 nio socket來說,Netty中的NioServerSocketChannel和NioSocketChannel分別封裝了
java.nio
中包含的 ServerSocketChannel和SocketChannel的功能。
對應原始碼解析文章:
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(一)之簡介》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(二)之 accept 操作》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(三)之 read 操作》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(四)之 write 操作》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(五)之 flush 操作》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(六)之 writeAndFlush 操作》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(七)之 close 操作》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(八)之 disconnect 操作》
1.2.5 ChannelEvent
如前所述,Netty是事件驅動的,其透過 ChannelEvent 來確定事件流的方向。一個ChannelEvent是依附於Channel的 ChannelPipeline來處理,並由ChannelPipeline呼叫ChannelHandler來做具體的處理。下麵是和 ChannelEvent相關的介面及類圖:
對於使用者來說,在ChannelHandler實現類中會使用繼承於ChannelEvent的MessageEvent,呼叫其 getMessage()方法來獲得讀到的ChannelBuffer或被轉化的物件。
對應原始碼解析文章:
-
《精盡 Netty 原始碼解析 —— ChannelHandler(一)之簡介》
-
《精盡 Netty 原始碼解析 —— ChannelHandler(二)之 ChannelInitializer》
-
《精盡 Netty 原始碼解析 —— ChannelHandler(三)之 SimpleChannelInboundHandler》
-
《精盡 Netty 原始碼解析 —— ChannelHandler(四)之 LoggingHandler》
-
《精盡 Netty 原始碼解析 —— ChannelHandler(五)之 IdleStateHandler》
-
《精盡 Netty 原始碼解析 —— ChannelHandler(六)之 AbstractTrafficShapingHandler》
1.2.6 ChannelPipeline
Netty 在事件處理上,是透過ChannelPipeline來控制事件流,透過呼叫註冊其上的一系列ChannelHandler來處理事件,這也是典型的攔截 器樣式。下麵是和ChannelPipeline相關的介面及類圖:
事件流有兩種,upstream事件和downstream事件。在ChannelPipeline中,其可被註冊的ChannelHandler既可以 是 ChannelUpstreamHandler 也可以是ChannelDownstreamHandler ,但事件在ChannelPipeline傳遞過程中只會呼叫匹配流的ChannelHandler。在事件流的過濾器鏈 中,ChannelUpstreamHandler或ChannelDownstreamHandler既可以終止流程,也可以透過呼叫 ChannelHandlerContext.sendUpstream(ChannelEvent)或 ChannelHandlerContext.sendDownstream(ChannelEvent)將事件傳遞下去。下麵是事件流處理的圖示:
從上圖可見,upstream event是被Upstream Handler們自底向上逐個處理,downstream event是被Downstream Handler們自頂向下逐個處理,這裡的上下關係就是向ChannelPipeline裡新增Handler的先後順序關係。簡單的理 解,upstream event是處理來自外部的請求的過程,而downstream event是處理向外傳送請求的過程。
服務端處 理請求的過程通常就是解碼請求、業務邏輯處理、編碼響應,構建的ChannelPipeline也就類似下麵的程式碼片斷:
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", new MyProtocolDecoder());
pipeline.addLast("encoder", new MyProtocolEncoder());
pipeline.addLast("handler", new MyBusinessLogicHandler());其中,MyProtocolDecoder是ChannelUpstreamHandler型別,MyProtocolEncoder是 ChannelDownstreamHandler型別,MyBusinessLogicHandler既可以是 ChannelUpstreamHandler型別,也可兼ChannelDownstreamHandler型別,視其是服務端程式還是客戶端程式以及 應用需要而定。
補充一點,Netty對抽象和實現做了很好的解耦。像org.jboss.netty.channel.socket包, 定義了一些和socket處理相關的介面,而org.jboss.netty.channel.socket.nio、 org.jboss.netty.channel.socket.oio等包,則是和協議相關的實現。
對應原始碼解析文章:
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(一)之初始化》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(二)之新增 ChannelHandler》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(三)之刪除 ChannelHandler》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(四)之 OutBound 事件的傳播》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(五)之 Inbound 事件的傳播》
-
《精盡 Netty 原始碼解析 —— ChannelPipeline(六)之異常的傳播》
1.2.7 Codec Framework
對於請求協議的編碼解碼,當然是可以按照協議格式自己操作ChannelBuffer中的位元組資料。另一方面,Netty也做了幾個很實用的codec helper,這裡給出簡單的介紹。
1)FrameDecoder:FrameDecoder內部維護了一個 DynamicChannelBuffer成員來儲存接收到的資料,它就像個抽象模板,把整個解碼過程模板寫好了,其子類只需實現decode函式即可。 FrameDecoder的直接實現類有兩個:(1)DelimiterBasedFrameDecoder是基於分割符 (比如\r\n)的解碼器,可在建構式中指定分割符。(2)LengthFieldBasedFrameDecoder是基於長度欄位的解碼器。如果協 議 格式類似“內容長度”+內容、“固定頭”+“內容長度”+動態內容這樣的格式,就可以使用該解碼器,其使用方法在API DOC上詳盡的解釋。
2)ReplayingDecoder: 它是FrameDecoder的一個變種子類,它相對於FrameDecoder是非阻塞解碼。也就是說,使用 FrameDecoder時需要考慮到讀到的資料有可能是不完整的,而使用ReplayingDecoder就可以假定讀到了全部的資料。
3)ObjectEncoder 和ObjectDecoder:編碼解碼序列化的Java物件。
4)HttpRequestEncoder和 HttpRequestDecoder:http協議處理。下麵來看使用FrameDecoder和ReplayingDecoder的兩個例子:
public class IntegerHeaderFrameDecoder extends FrameDecoder {
protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buf) throws Exception {
if (buf.readableBytes() 4) {
return null;
}
buf.markReaderIndex();
int length = buf.readInt();
if (buf.readableBytes() buf.resetReaderIndex();
return null;
}
return buf.readBytes(length);
}
}而使用ReplayingDecoder的解碼片斷類似下麵的,相對來說會簡化很多。
public class IntegerHeaderFrameDecoder2 extends ReplayingDecoder {
protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buf, VoidEnum state) throws Exception {
return buf.readBytes(buf.readInt());
}
}就實現來說,當在ReplayingDecoder子類的decode函式中呼叫ChannelBuffer讀資料時,如果讀失敗,那麼 ReplayingDecoder就會catch住其丟擲的Error,然後ReplayingDecoder接手控制權,等待下一次讀到後續的資料後繼 續decode。
對應原始碼解析文章:
-
《精盡 Netty 原始碼解析 —— Codec 之 ByteToMessageDecoder(一)Cumulator》
-
《精盡 Netty 原始碼解析 —— Codec 之 ByteToMessageDecoder(二)FrameDecoder》
-
《精盡 Netty 原始碼解析 —— Codec 之 MessageToByteEncoder》
-
《精盡 Netty 原始碼解析 —— Codec 之 ByteToMessageCodec》
-
《精盡 Netty 原始碼解析 —— Codec 之 MessageToMessageCodec》
1.2.8 小結
儘管該文行至此處將止,但該文顯然沒有將Netty實現原理深入淺出的說全說透。當我打算寫這篇文章時,也是一邊看Netty的程式碼,一邊總結些可寫的東 西,但前後斷斷續續,到最後都沒了多少興緻。我還是愛做一些原始碼分析的事情,但精力終究有限,並且倘不能把原始碼分析的結果有條理的托出來,不能產生有意義 的心得,這分析也沒什麼價值和趣味。而就分析Netty程式碼的感受來說,Netty的程式碼很漂亮,結構上層次上很清晰,不過這種面向介面及抽象層次對程式碼 跟蹤很是個問題,因為跟蹤程式碼經常遇到介面和抽象類,只能藉助於工廠類和API DOC,反覆對照介面和實現類的對應關係。就像幾乎任何優秀的Java開源專案都會用上一系列優秀的設計樣式,也完全可以從樣式這一點單獨拿出一篇分析文 章來,儘管我目前沒有這樣的想法。而在此文完成之後,我也沒什麼興趣再看Netty的程式碼了。
另外,Netty 中,提供了大量為了提升效能的工具類:
-
《精盡 Netty 原始碼解析 —— Util 之 Future》
-
《精盡 Netty 原始碼解析 —— Util 之 FastThreadLocal》
-
《精盡 Netty 原始碼解析 —— 精盡 Netty 原始碼解析 —— Util 之 Recycler》
-
《精盡 Netty 原始碼解析 —— Util 之 HashedWheelTimer》
-
《精盡 Netty 原始碼解析 —— Util 之 MpscUnboundedArrayQueue》
1.3 精盡 Netty 面試題
正在整理 ing…
如果胖友對 NIO 不瞭解,可以看看如下入門的內容:
-
《精盡 Netty 原始碼分析 —— NIO 基礎(一)之簡介》
-
《精盡 Netty 原始碼分析 —— NIO 基礎(二)之 Channel》
-
《精盡 Netty 原始碼分析 —— NIO 基礎(三)之 Buffer》
-
《精盡 Netty 原始碼分析 —— NIO 基礎(四)之 Selector》
-
《精盡 Netty 原始碼分析 —— NIO 基礎(五)之示例》