Netty 框架學習 —— Netty 組件與設計


Channel、EventLoop 和 ChannelFuture

這一節將對 Channel、EventLoop 和 ChannelFuture 類進行討論,它們組合在一塊兒,能夠被認爲是 Netty 網絡抽象的表明:編程

  • Channel —— Socket
  • EventLoop —— 控制流、多線程處理、併發
  • CHannelFuture —— 異步通知

1. Channel 接口

Netty 的 Channel 接口對應 Java 網絡編程的 Socket,大大下降了直接使用 Socket 類的複雜性。此外,Channel 也擁有其餘預約義的實現類:服務器

  • EmbeddedChannel:測試 ChannelHandler
  • LocalServerChannel:用於同一個 JVM 內部實現 client 和 server 之間的通訊
  • NioSocketChannel:異步的客戶端 TCP Socket 鏈接
  • NioServerSocketChannel:異步的服務器端 TCP Socket 鏈接
  • NioDatagramChannel:異步的 UDP 鏈接
  • NioSctpChannel:異步的客戶端 Sctp 鏈接
  • NioSctpServerChannel:異步的 Sctp 服務器端鏈接
  • OioSocketChannel:同步的客戶端 TCP Socket 鏈接
  • OioServerSocketChannel:同步的服務器端 TCP Socket 鏈接
  • OioDatagramChannel:同步的 UDP 鏈接
  • OioSctpChannel:同步的 Sctp 服務器端鏈接
  • OioSctpServerChannel:同步的客戶端 TCP Socket 鏈接

2. EventLoop 接口

EventLoop 用於處理鏈接的生命週期中所發生的事件,下圖說明了 Channel、EventLoop、Thread 以及 EventLoopGroup 之間的關係網絡

這些關係是:多線程

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

3. ChannelFuture 接口

Netty 全部的 IO 操做都是異步的,一個操做可能不會當即返回結果,所以咱們須要一種用於在以後的某個時間點肯定其結果的方法。Netty 提供了 ChannelFuture 接口,其 addListener() 方法註冊一個 ChannelFutureListener,以便在某個操做完成時(不管是否成功0獲得通知)併發


ChannelHandler 和 ChannelPipeline

1. ChannelHandler 接口

ChannelHandler 能夠看做是負責處理入站和出站數據的應用程序邏輯的容器,例如將數據從一個格式轉換爲另外一種格式,處理拋出的異常等等。ChannelInboundHandler 是一個常用的子接口,這種類型的 ChannelHandler 接收入站事件和數據,這些數據隨後將被你的業務邏輯鎖處理。當你想要給客戶端發送響應時,也能夠從 ChannelInboundHandler 沖刷數據,一般應用程序的業務邏輯一般駐留在一個或者多個 ChannelInboundHandler 中異步

2. ChannelPipeline 接口

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

ChannelHandler 安裝到 ChannelPipeline 中的過程以下所示:oop

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

ChannelHandler 能夠看做是處理往來 ChannelPipeline 事件(包括數據)的任何代碼的通用容器,使事件流通過 ChannelPipeline 是 ChannelHandler 的工做,在應用程序的初始化或者引導階段被安裝。這些 ChannelHandler 接收事件、執行所實現的業務邏輯,並將數據傳遞給鏈中的下一個 ChannelHandler。它們的執行順序由它們被添加的順序所決定。實際上,ChannelPipeline 就是這些 ChannelHandler 的編排順序測試

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

在 Netty 中有兩種發送消息的方式,能夠直接寫到 Channel 中,也能夠寫到和 ChannelHandler 相關聯的 ChannelHandlerContext 對象中。前一種方式將會致使消息從 ChannelPipeline 的尾端開始流動,後者將致使消息從 ChannelPipeline 中的下一個 ChannelHandler 開始流動


編碼器和解碼器

當你經過 Netty 發送或者接收一個消息時,就會發生一次數據轉換。入站消息會被解碼,即從字節轉換成另外一種格式,一般是一個 Java 對象。若是是出站消息,則會發生相反方向的轉換,從當前格式被編碼爲字節。爲此,Netty 爲編碼器和解碼器提供了不一樣類型的抽象類,這些基類的名稱將相似於 ByteToMessageDecoder 或 MessageToByteEncoder。對於一些特殊類型,可能還會有 ProtobufEncoder 和 ProtobufDecoder 這樣的名稱,用來支持 Google 的 Protocol Buffers

使用 Netty 提供的編碼器/解碼器,你會發現對於入站數據來講,channelRead 方法/事件已經被重寫。對於每一個從入站 Channel 讀取的消息,將調用重寫後的 channelRead 方法。隨後,它將調用解碼器提供的 decode() 方法,將已解碼的字節轉發給 ChannelPipeline 中的下一個 ChannelInboundHandler。出站消息是反過來的,編碼器將消息轉換爲字節,並將它們轉發給下一個 ChannelOutboundHandler


引導

Netty 的引導類爲應用程序的網絡層配置提供了容器,這涉及將一個進程綁定到某個指定的端口,或者將一個進程鏈接到另外一個運行在某個指定主機的指定端口上的進程。一般咱們把前面的用例稱爲引導一個服務器,後面的用例稱爲引導一個客戶端。所以,有兩種類型的引導:一種用於客戶端(Bootstrap),而另外一種(ServerBootstrap)用於服務器

兩種類型的引導類區別以下:

  • ServerBootstrap 將綁定到一個端口,由於服務器必需要監聽鏈接,而 Bootstrap 則是由想要鏈接到遠程節點的客戶端應用程序使用

  • 引導一個客戶端只須要一個 EventLoopGroup,可是一個 ServerBootstrap 則須要兩個。由於服務器須要兩組不一樣的 Channel,第一組只包含一個 ServerChannel,表明服務器自身已綁定到某個本地端口的正在監聽的套接字,而第二組將包含全部已建立的用來處理傳入客戶端鏈接的 Channel

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

相關文章
相關標籤/搜索