Netty學習之組件和設計
前言
前面我們簡單地介紹了Netty,然后學習了一個簡單的小例子,接下來我們來學習Netty的組件概要及組件之間的關系。
Channel,EventLoop,ChannelFuture
對于Netty來說,Channel、EventLoop、ChannelFuture三者的結(jié)合,就是Netty的網(wǎng)絡抽象
- Channel代表的是Socket
- EventLoop代表的是控制流,多線程以及并發(fā)
- ChannelFuture代表的是異步通知
Channel接口
Netty中的Channel接口,減少了直接與Socket交互的復雜性,Netty中提供了眾多的預定義Channel
- EmbeddedChannel
- LocalServerChannel
- NioDatagramChannel
- NioSctpChannel
- NioSocketChannel
- NioServerSocketChannel
EventLoop接口
EventLoop定義了Netty處理事件的核心抽象。
Netty中的Channel、EventLoop、Thread以及EventLoopGroup的關系如下
- 一個EventLoopGroup包含一個或者多個EventLoop
- 一個EventLoop在其生命周期中綁定一個線程
- 一個EventLoop處理的所有事件均由其對應的線程來處理(避免了同步需要加鎖的問題)
- 一個Channel在其生命周期中注冊唯一一個EventLoop
- 一個EventLoop可以同于處理一個或者多個Channel
具體的圖例如下所示(圖片來自《Netty In Action》)

ChannelFuture接口
在Netty中的所有操作都是異步的,因為所有的操作不太可能立即返回,所以我們需要有某個東西可以讓我們在需要的時候來獲取操作的結(jié)果,Netty中的ChannelFuture就是這個用途,通過其addListener()方法來注冊ChannelFutureListener實例,可以在操作完成之后獲得通知。
ChannelHandler,ChannelPipeline
如果說上面的三者是Netty的網(wǎng)絡抽象,那么ChannelHanlder、ChannelPipeline就是Netty中的數(shù)據(jù)控制流以及應用的處理邏輯了。
ChannelHandler接口
從開發(fā)者的角度來講,ChannelHandler是我們主要的操作對象,應用的操作邏輯都位于ChannelHandler中,ChannelHandler中的方法由網(wǎng)絡事件進行觸發(fā)和調(diào)用,ChannelHandler可以用于任何用途,比如講數(shù)據(jù)從一個格式轉(zhuǎn)換為另一種格式或者處理異常等。
有兩個主要的子接口,ChannelInboundHandler、ChannelOutboundHandler,用于處理兩種不同類型的數(shù)據(jù)(輸入的數(shù)據(jù)以及輸出的數(shù)據(jù))
同時,在Netty中提供了很多Adapter,用于提高開發(fā)者的開發(fā)效率,并且這些適配器會自動將事件傳遞給下一個處理器
- ChannelHandlerAdapter
- ChannelInboundHandlerAdapter
- ChannelOutboundHanlderAdapter
- ChannelDuplexHandlerAdapter
編解碼器
由于在網(wǎng)絡中發(fā)送的數(shù)據(jù)都是二進制格式,所以,當使用Netty進行網(wǎng)絡開發(fā)時,我們同樣需要對數(shù)據(jù)進行編碼和解碼
編碼用于將數(shù)據(jù)轉(zhuǎn)換成二進制格式
解碼用于將二進制格式轉(zhuǎn)換成我們需要的格式
Netty中提供了一些常用的編解碼器,這些編解碼器本質(zhì)上也是ChannelHandler,如ByteToMessageDecoder、MessageToByteEncoder
Channelpipeline接口
ChannelPipeline提供了將所有的ChannelHandler連接其他的容器,也就是說,在Netty中,所有的ChannelHandler通過ChannelPipeline串聯(lián)起來。同時,ChannelPipeline提供了在該鏈中進行事件傳播的方法。
ChannelPipeline通過下面的方式注冊ChannelHandler
- ServerBootstrap注冊一個ChannelInitializer的實現(xiàn)類
- 當ChannelInitializer.initChannel()被調(diào)用時,通過ChannelInitializer在ChannelPipeline注冊一系列的ChannelHandler
- ChannelInitializer將自己從ChannelPipeline中移除
ChannelHandler根據(jù)初始化階段注冊的順序在ChannelPipeline中傳遞事件。
Netty中的事件可以通過每個方法中的ChannelHandlerContext來傳遞給下一個Handler,由于我們通常只關注某一個事件,所以Netty提供了ChannelInboundHandlerAdapter以及ChannelOutboundHandlerAdapter。
在Netty中有兩種方式可以發(fā)送數(shù)據(jù)
- 直接通過Channel發(fā)送,會從頭到尾發(fā)送數(shù)據(jù)
- 通過ChannelHandler綁定的ChannelHandlerContext進行發(fā)送,只會講數(shù)據(jù)傳遞給下一個ChannelHandler
Bootstrapping
Netty中的Bootstap類提供了應用的網(wǎng)絡層配置的容器
根據(jù)對象的不同,有兩種不同類型的bootstrap
- ServerBootstrap,用于綁定本地端口,需要兩個EventLoopGroup(可以是同一個)
- bootstrap,用于連接遠程主機及端口,只需要一個EventLoopGroup
一個服務器需要兩種不同類型的Channel,一個是用于存放一個單一的用于表示服務器自己監(jiān)聽的ServerChannel,一個用于維護所有已經(jīng)建立連接的Channel,也就是accept()操作之后的連接
總結(jié)
本小節(jié)我們主要學習Netty的核心組件概要及組件的關系,包括了Channel、EventLoop、EventLoopGroup、ChanneHandler、ChannelPipeline、Boostrap等,不同的組件有不同的功能,不同的組件之間又相互交互,共同構(gòu)成完整的Netty應用。