Netty4 ChannelHandler 概述

本節主要介紹 Netty ChannelHandler 事件概述,並詳細介紹各個事件方法的觸發時機,爲下篇關於事件傳播機制打下堅實基礎。

NIO 相關的核心類圖如下:
在這裏插入圖片描述
下面一一對上述類做一個簡單的介紹,下文還會其進行更爲詳細的解讀。

  • ChannelHandler
    Netty Channel事件的基礎接口,只定義與 Handler 的管理接口相關,具體如下:
    • void handlerAdded(ChannelHandlerContext ctx)
      在調用 DefaultChannelPipeline 的 addLast(add*) 將事件監聽器添加到事件處理鏈條時調用。
    • void handlerRemoved(ChannelHandlerContext ctx)
      在調用DefaultChannelPipeline 的 addLast(add*) 發生異常時被調用;當通道關閉後,通道取消註冊後,同時會觸發通道移除事件,具體調用入口:DefaultChannelPipeline 的內部類 HeadContext 的 channelUnregistered。

  • ChannelInboundHandler
    入端類型的事件處理器。
    • void channelRegistered(ChannelHandlerContext ctx)
      通道註冊到 Selector 時觸發。客戶端在調用 connect 方法,通過 TCP 建立連接後,獲取 SocketChannel 後將該通道註冊在 Selector 時或服務端在調用bind 方法後創建 ServerSocketChannel,通過將通道註冊到 Selector 時監聽客戶端連接上時被調用。
    • void channelUnregistered(ChannelHandlerContext ctx)
      通道取消註冊到Selector時被調用,通常在通道關閉時觸發,首先觸發channelInactive 事件,然後再觸發 channelUnregistered 事件。
    • void channelActive(ChannelHandlerContext ctx)
      通道處於激活的事件,在 Netty 中,處於激活狀態表示底層 Socket 的isOpen() 方法與 isConnected() 方法返回 true。
    • void channelInactive(ChannelHandlerContext ctx)
      通道處於非激活(關閉),調用了 close 方法時,會觸發該事件,然後觸發channelUnregistered 事件。
    • void channelRead(ChannelHandlerContext ctx, Object msg)
      通道從對端讀取數據,當事件輪詢到讀事件,調用底層 SocketChanne 的 read 方法後,將讀取的字節通過事件鏈進行處理,NIO 的觸發入口爲AbstractNioByteChannel 的內部類 NioByteUnsafe 的 read 方法。
    • void channelReadComplete(ChannelHandlerContext ctx)
      處理完一次通道讀事件後觸發,在 Netty 中一次讀事件處理中,會多次調用SocketChannel 的 read方法。觸發入口爲AbstractNioByteChannel 的內部類NioByteUnsafe 的 read 方法。
    • void userEventTriggered(ChannelHandlerContext ctx, Object evt)
      觸發用戶自定義的事件,目前只定義了ChannelInputShutdownEvent(如果允許半關閉(輸入端關閉而服務端不關閉))事件。
    • void channelWritabilityChanged(ChannelHandlerContext ctx)
      Netty 寫緩存區可寫狀態變更事件(可寫–》不可寫、不可寫–》可寫),入口消息發送緩存區ChannelOutboundBuffer。

  • void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
    異常事件。
  • ChannelOutboundHandler
    出端類型的事件處理器。
    • void bind(ChannelHandlerContext ctx, SocketAddress add, ChannelPromise p)
      調用ServerBootstrap 的 bind 方法的處理邏輯。綁定操作,服務端在啓動時調用bind方法時觸發(手動調用bind)。
    • void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,SocketAddress localAddress, ChannelPromise promise)
      連接操作,客戶端啓動時調用connect方法時觸發(手動調用connect)。
    • void disconnect(ChannelHandlerContext ctx, ChannelPromise promise)
      斷開連接操作(手動調用disconnect)
    • void close(ChannelHandlerContext ctx, ChannelPromise promise)
      關閉通道,手動調用Channel#close方法時觸發。(手動調用close)
    • void deregister(ChannelHandlerContext ctx, ChannelPromise promise)
      調用Channel#deregister時觸發。(手動調用deregister)。
    • void read(ChannelHandlerContext ctx) throws Exception
      註冊讀事件,並不是觸發網絡讀寫事件。
    • void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception
      調用調用 Channel 的 write(底層 SocketChannel 的 write)時觸發。
    • void flush(ChannelHandlerContext ctx)
      調用調用Channel#flush(SocketChannel#flush)時觸發。

  • ChannelDuplexHandler
    雙向 Handler,包含 Inbound 和 outbound 事件。
  • ByteToMessageDecoder
    解碼器:字節流解碼成一條一條的消息(Message、協議對象)。
  • MessageToByteEncoder
    編碼器:消息(協議對象)編碼成二進制字節流。
  • AbstractTrafficShapingHandler
    流量整形,將在後續章節中詳細介紹。

上述詳細的介紹了NettyChannel的類繼承體系,並重點介紹了ChannelInboundHandler 與 ChannelOutboundHandler 每個方法的含義已經觸發時機,接下來再談一點我對這兩個 Handler 的一些理解。

ChannelInboundHandler入端操作,可以看出基本上是都是由事件選擇器(NIO Selector事件就緒選擇)進行觸發,事件名稱以 channel 開頭,例如channelRead。

ChannelOutboundHanlder出端操作,其觸發點除了 read 事件外都是通過調用api(例如bind、connect、close、write)。

本文就介紹到這裏了,主要目的是讓大家對 Netty ChannelHandler 有一個基本的認識,爲後續文章打下堅實的基礎。

最後以一個思考題結束本文的講解:ChannelInboundHandler 的channelRead 事件與 ChannelOutboundHandler 的 read 事件有什麼區別呢?

溫馨提示:如果需要與筆者關於上述問題進行交流,可以加筆者微信:dingwpmz。


好了,本文就介紹到這裏了,您的點贊與轉發是對我持續輸出高質量文章最大的鼓勵。

歡迎加筆者微信號(dingwpmz),拉您如技術交流加羣探討,筆者優質專欄目錄:
1、源碼分析RocketMQ專欄(40篇+)
2、源碼分析Sentinel專欄(12篇+)
3、源碼分析Dubbo專欄(28篇+)
4、源碼分析Mybatis專欄
5、源碼分析Netty專欄(18篇+)
6、源碼分析JUC專欄
7、源碼分析Elasticjob專欄
8、Elasticsearch專欄(20篇+)
9、源碼分析MyCat專欄
10、源碼分析 Canal
11、源碼分析Kafka










發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章