Netty組件入門學習

Channel、EventLoop和ChannelFuture

  1. Channel——Socket;
  2. EventLoop——控制流、多線程處理、併發
  3. ChannelFuture異步通知

Channel接口

基於I/O操做(例如:bind()、connect()、read()和write())依賴於底層網絡傳輸提供的原語。在基於Java的網絡編程中,其基本構造爲類Socket。

Netty的Channel接口所提供的API,大大下降了直接使用Socket類的複雜性。

Channel擁有許多預約義的、專門化實現的普遍類層次結構的根,以下:編程

  1. EmbeddedChannel
  2. LocalServerChannel
  3. NioDatagramChannel
  4. NioSctpChannel
  5. NioSocketChannel

EventLoop接口

EventLoop定義了Netty的核心抽象,用於處理鏈接的生命週期中所發生的事件。服務器

Channel、EventLoop、Thread、EventLoopGroup關係示意圖網絡

關係圖

  • 一個EventLoopGroup包含一個或者多個EventLoop
  • 一個EventLoop在它的生命週期內只和一個Thread綁定
  • 全部由EventLoop處理的I/O事件都將在它專有的Thread上被處理
  • 一個Channel在它的生命週期內只註冊於一個EventLoop
  • 一個EventLoop可能會被分配一個或多個Channel

一個給定Channel的I/O操做都是由相同的Thread執行的,實際上消除了對於同步的須要多線程

ChanneFuture接口

Netty中全部的I/O操做都是異步的,由於一個操做不可能當即返回,因此咱們須要一種用於在以後的某個時間點肯定其結果的方法。

所以Netty提供了ChannelFuture接口,其addListener()方法註冊了一個ChannelFutureListener,以便在某個操做完成時(不管是否成功)獲得通知。併發

ChannelHandler和ChannelPipeline

主要用來管理數據流已經執行應用程序處理邏輯異步

ChannelHandler接口

ChannelHandler充當了全部處理入站和出站數據的應用程序邏輯的容器。

ChannelHandler可專門用於幾乎任何類型的動做,例如將數據從一種格式轉換爲另一種格式,或者處理轉換過程當中所拋出的異常。

ChannelHandler能夠用來接收入站事件和數據,隨後使用應用程序的業務邏輯進行處理。當你的客戶端須要發送響應時,能夠從ChannelInboundhandler沖刷數據。

你的應用程序的業務邏輯一般駐留在一個或者多個ChannelInboundHandler中。oop

ChannelPipeline

ChannelPipeline是ChannelHandler鏈的容器,並定義用於在該鏈上傳播入站和出站事件流的API。當Channel被建立時,它會被自動地分配到它專屬的ChannelPipeline。
編碼

ChannelHandler被安裝到ChannelPipeline中過程以下:spa

  1. 一個ChannelInitializer的實現被註冊到了ServerBootstrap中
  2. 當ChannelInitializer.initChannel()方法被調用時,ChannelInitalizer將在ChannelPipeline中安裝一組自定義的ChannelHandler
  3. ChannelInitializer將它本身從ChannelPipeline中移除

 ChannelHandler可讓事件流經ChannelPipeline,它們是在應用程序的初始化或者引導階段被安裝的。這些對象接收事件、執行它們所實現的處理邏輯,並將數據傳遞給鏈中的下一個ChannelHandler。它們的執行順序是由它們被添加的順序決定的

ChannelPipeline是這些ChannelHandler的編排順序。線程

入站和出站ChannelHandler能夠被安裝到同一個ChannelPipeline中。若是一個消息或者任何其餘的入站事件被讀取,那麼它會從ChannelPipeline的頭部開始流動,並被傳遞給第一個ChannelInboundHandler。這個ChannelHandler不必定會實際地修改數據,具體取決於它的具體功能,在這以後,數據將會被傳遞給鏈中的下一個ChannelInboundHandler。最終,數據會到達ChannelPipeline的尾端,屆時,全部處理就都結束了。

出站數據將會從ChannelOutboundHandler鏈的尾端開始流動,直到它到達鏈的頭部爲止。在這以後,出站數據將會到達網絡傳輸層。

經過使用做爲參數傳遞到每一個方法的ChannelHandlerContext,事件能夠被傳遞給當前ChannelPipeLine中的下一個ChannelHandler。由於用戶並非關心全部的事件,所以Netty提供了抽象類ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter。經過調用ChannelHandlerContext上的對應的方法,均可以簡單地將事件傳遞給下一個ChannelHandler的方法的實現。

當ChannelHandler被添加到ChannelPipeline時,它將會被分配一個ChannelHandlerContext,它表明了Channel和ChannelPipeline之間的綁定。雖然這個對象能夠被用於獲取底層的Channel,可是它主要仍是被用於出站寫數據。

在Netty中,有兩種發送消息的方式:

  1. 直接寫到Channel中,會致使消息從ChannelPipeline的尾端開始流動
  2. 寫到和ChannelHandler相關聯的ChannelHandlerContext對象中,會致使消息從ChannelPipeline中的下一個ChannelHandler開始流動

若是將兩個類別(Inboud和Outbound)的ChannelHandler都混合添加到一個ChannelPipeline會發生什麼?

雖然ChannelInboundHandler和ChannelOutboundHandler都擴展自ChannelHandler,可是Netty能夠區分兩種Handler的實現,並確保數據只會在具備相同定向類型的兩個ChannelHandler之間傳遞。

深刻了解ChannelHandler

不一樣類型的ChannelHandler各自的功能主要取決於它們的超類。Netty以適配器類的形式提供了大量默認的ChannelHandler實現,其旨在簡化應用程序處理邏輯的開發過程。

這些適配器類能夠自動將事件轉發到ChannelPipeline中的下一個ChannelHandler,因此你能夠只重寫那些你想要特殊處理的方法和事件。

爲何須要適配器?

有一些適配器類能夠將編寫自定義的ChannelHanlder所須要的努力降到最低限度,由於它們提供了定義在對應接口中的全部方法的默認實現。
經常使用的適配器類有:

  • ChannelHandlerAdapter
  • ChannelInboundHandlerAdapter
  • ChannelOutboundHandlerAdapter
  • ChannelDuplexHandler

編碼解碼器

全部由Netty提供的編碼/解碼適配器類都實現了ChannelOutboundHandler或者ChannelInboundHandler接口。

對於入站數據,channelRead方法已經被重寫了。對於每個從入站Channel讀取的消息,這個方法都會被調用。隨後,它將調用由預置解碼器提供的decode()方法,並將已解碼的字節轉發給ChannelPipeline中的下一個ChannelHandler,出站相反。

抽象類SimpleChannelInboundHandler

最多見的一個狀況,你的應用程序會利用一個ChannelHandler來接受解碼消息,並對該數據應用業務邏輯。要建立一個這樣的ChannelHandler,只須要擴展SimpleChannelInboundHandler<T>,其中<T>是你要處理的消息的Java類型。

在這個ChannelHandler中,你將須要重寫基類的一個或者多個方法,而且獲取一個ChannelHandlerContext的引用,這個引用將做爲參數傳遞給ChannelHandler的全部方法。

在這種類型的ChannelHandler中,最重要的方法是channelRead0(ChannelHandlerContext , T)。除了要求不阻塞當前的I/O線程以外,其具體實現徹底取決於你。

引導

Netty的引導類爲應用程序的網絡層配置提供了容器。

  1. 用於客戶端(Bootstrap)引導,將一個進程鏈接到另外一個運行在某個指定主機的指定端口上的進程。
  2. 用於服務器(ServerBootstrap)引導,將一個進程綁定到某個指定的端口

Bootstrap類比較

類別 Bootstrap ServerBootstrap
網絡編程中的做用 鏈接到遠程主機和端口 綁定到一個本地端口
EventLoopGroup的數目 1 2

區別分析:

  1. ServerBootstrap將綁定到一個端口,由於服務器必需要監聽鏈接,而Bootstrap則是由想要鏈接到遠程節點的客戶端應用程序所使用的。
  2. 爲何服務端須要兩個EventLoopGroup(能夠是同一個實例)?由於服務器須要兩組不一樣的Channel。第一組將只包含一個ServerChannel,表明服務器自身的已綁定到某個本地端口第二次正在監聽的套接字。第二組包含全部已經建立的用來處理傳入客戶端鏈接(對於每一個服務器已經接受的鏈接都一個)的Channel。

3.與ServerChannel相關聯的EventLoopGroup將分配一個負責爲傳入鏈接請求建立Channel的EventLoop。一旦鏈接被接受,第二個EventLoopGroup就會給它的Channel分配一個EventLoop。

具備兩個EventLoopGroup的服務器

EventLoopGroup服務器

相關文章
相關標籤/搜索