天天看點

Netty源碼分析-概述

大家好,我是小森。前段時間我們學習了Netty架構,并完成了Netty架構主要元件的入門介紹(沒有學習的小夥伴可以看這Netty架構入門);在這個系列中圍繞服務端與用戶端通信的示例展開學習,對Netty的Bytebuf、ChannelHandler、ChannelPipeline、Bootstrap和EventLoop等子產品進行了學習,因為是入門級别是以講的也不是很深入。但我相信通過這個入門系列的學習你已經學會了Netty架構的使用并且會産生一些思考與問題,例如下面這些:

  • Netty的Bootstrap服務端與用戶端引導啟動時分别做了些什麼?
  • Netty的Bytebuf是如何做到堆内零拷貝的?池化技術又是如何實作的?
  • Netty的ChannelPipeline、ChannelHandlerContext設計
  • Netty的Reactor模式是怎樣實作的,又分為那些模型
  • ……

那麼我們将有閱讀源碼的形式了解上面或更多問題。在做件事情前再來一起回顧下,或者說閱讀源碼的一個大綱吧。

一、Bootstrap

Bootstrap是一個引導程式,将會重它開始,就像程式啟動一樣先進行引導再進入業務流程。在這個章節中會分别對服務端的引導和用戶端的引導以及AbstractBootstrap類進行閱讀分析,過程就像這張類圖一樣:

Netty源碼分析-概述

因為引導還會涉及到EventLoop、ChannelHandler等内容,這一章節也隻會簡單的描述下它們是如果被初始的,在引導過程中起到的作用,最後以回顧整個引導流程結束這一章節

二、EventLoop與EventLoopGroup

EventLoop在入門篇的示例中并沒有明确的用到,但我們使用過NioEventLoopGroup,EventLoop将會在内部使用到;根據流程在用戶端打開連接配接或者在服務端打開監聽端口後将建立Channel,而Channel将會被托管在EventLoop中,而EventLoop的建立由EventLoopGroup初始。過程大概如下圖:

Netty源碼分析-概述

Netty架構中的事件驅動模型使用Reactor模型實作,支援單Reactor單線程、單Reactor多線程、主從Reactor多線程;另外在EventLoop中還包含了Worker;這個Worker的作用是區分I/O事件與非I/O任務,但這些都交由Reactor線程處理。

Channel

用戶端建立一個連接配接或者服務端收到連接配接請求都會建立一個Channel,所有的I/O事件都由Channel産生,這些事件包含read、write、connet、accept、close。Channel為使用者提供了:

  • 目前網絡連接配接通道的狀态
  • 網絡連接配接的配置資訊
  • 異步的網絡I/O操作,操作傳回ChannelFuture執行個體,通過ChannelFuture可以操作異步的狀态,例如取消、關閉等

不同的協定與不同的阻塞類型的連接配接都有與之對應的Channel類型,下面是常用的Channel類型:

  • NioSocketChannel 異步的用戶端 TCP Socket 連接配接。
  • NioServiceSocketChannel 異步的伺服器端 TCP Socket 連接配接。
  • NioDatagramChannel 異步的 UDP 連接配接。
  • NioSctpChannel 異步的用戶端 Sctp 連接配接。
  • NioSctpServiceChannel 異步的 Sctp 伺服器端連接配接
  • EpollSocketChannel 異步的用戶端TCP Socket連接配接,底層使用epoll
  • EpollServiceSocketChannel異步的伺服器端 TCP Socket 連接配接,底層使用epoll

當然不光有上面列舉的Channel類型就不一一列舉了,這次的閱讀也隻會涉及Nio部分。

ChannelHandler、ChannelHandlerContext

ChannelHandler是一個處理Channel事件的接口,通過ChannelHandler可以處理任一的網絡I/O事件與資料,引導過程會使用ChannelPipeline将多個ChannelHandler串起來。通常會通過繼承ChannelInboundHandler與ChannelOutboundHandler兩個子接口類型來處理業務邏輯,這些業務邏輯包含資料的編碼、解碼、讀取、寫入以及事件傳遞等待事情。在這其中有一個很重要的角色ChannnelHandlerContext,它的作用是将對應的ChannelHandler托管,在ChannelPipeline中起到事件向下傳遞與調用ChannelHandler的作用,另外還存儲着目前Channel的相關上下文資訊等。

ChannelPipeline

ChannelPipeline在Netty中起着一個很重要的作用,因為有它讓Netty在處理各種各樣的業務情況時有了很強擴充性與适應性,使得業務可以在運作時對整個ChannelPipeline中的過濾器(這裡的過濾器實作類型都是ChannelHandler)進行調整以支援不同的業務形态。下面通過源碼中的一張注釋圖來看看ChannelPipeline是如何工作的:

Netty源碼分析-概述

在ChannelPipeline中會區分入站(ChannelInboundHanndler類型)與出站(ChannelOutboundHandler類型)的過濾器進行自動編排,ChannelPipeline中使用一張連結清單存儲着所有ChannelHandler,先後順序由引導時插入到連結清單中的順序決定,但有時會混合着入站與出站,是以ChannelPipeline會有一個處理方向的概念,如果是處理入站事件時方向就是入站,會過濾不是目前方向上的ChannelHandler。具體的過程留給後文吧。

最後

現在穩定的版本是Netty4,是以源碼的閱讀與分析與将會使用Netty4的版本。

Netty的源碼位址:https://github.com/netty/netty.git

精彩推薦:

Netty源碼解析-引導(一)服務端啟動

Netty源碼解析-EventLoop(二)之EventLoopGroup初始化

更多超前内容請關注:

Netty源碼分析-概述