channelHandler 在Netty 4.x版本有了至關大的改動html
http://netty.io/wiki/new-and-noteworthy.html 官網的更新改進說明。promise
如下節選官網更新說明的部分中文翻譯:ide
「spa
在3.x時代,全部的I/O操做都會建立一個新的ChannelEvent對象。對每一個讀或寫的操做,還會額外建立一個新的ChannelBuffer對象。因爲將資源管理和buffer的池化交給了JVM,這實際上極大地簡化了Netty的內部實現。可是,基於Netty開發的應用在高負載下運行時,有時會觀察到GC(Garbage Collection)的壓力增大或變化不定,這些問題的根源也來自於這裏。翻譯
4.0經過把事件對象替換爲直接與類型相對應(譯者注:原文爲strongly typed,可是我以爲直譯爲強類型不太容易理解)的方法調用,幾乎徹底避免了事件對象的建立。3.x中,有相似於handleUpstream()和handleDownstream()這種可以捕獲全部相關類型事件的處理器方法,4.0中你將不會再看到它們的身影了。全部的事件類型如今都有各自對應的處理器方法:設計
「3d
」全部這些變化意味着用戶沒法去擴展ChannelEvent這個已經不存在的接口了。那用戶要怎樣才能定義他或她本身的事件類型呢,就像IdleStateEvent?4.0中的ChannelHandler有一個處理器方法叫作userEventTriggered(),它就是被設計用來知足這種特殊的用戶需求。netty
「code
4.x版本中簡化了channel 狀態模型(Simplified channel state model):htm
3.x版本的:
在4.x版本中:
ChannelOpen ChannelBound 和ChannelConnected 合併到ChannelActive.ChannelDisconnected ChannelUnbound ChannlClosed合併到ChannelInactive中
以下圖所示:
在Netty4.0.12的源代碼中咱們能夠看到AbstractChannel中的:
AbstractUnsafe{
...//調用fireChannelActive()
private void register0(ChannelPromise promise)
public final void bind(final SocketAddress localAddress, final ChannelPromise promise)
...//調用fireChannelInactive()
public final void disconnect(final ChannelPromise promise)
public final void close(final ChannelPromise promise)
}
..值得注意的是官網還特地提示了ChannelRegister和ChannelOpen和ChannelClosed有很大的區別
引入翻譯:"channelRegistered和channelUnregistered這兩個事件與channelOpen和channelClosed具備的意義是不同的。它們(channelRegistered和channelUnregistered)是在支持Channel的動態註冊、註銷以及再註冊時被引入的"
如圖所示。註冊和註銷僅僅用於每次的操做。
如下是我的口水:
貌似這麼作的好處在於。把channel的異常放在一個方法內統一處理。在3.x的開發過程當中發現。不少時候咱們想要的只是一個結果。服務端數據在客戶端channel斷開鏈接。解綁定。關閉3中狀態時,須要將相對應的信息數據處理掉。在4.x版本中將這三個事件整合以後。只須要統一的處理就行了。
1 // 管道從不活躍狀態 轉到 活躍狀態 觸發 2 @Override 3 public void channelActive(ChannelHandlerContext ctx) throws Exception { 4 final Channel channel = ctx.channel(); 5 if(channel.isOpen()){ 6 // 管道 活躍的 而且是開啓狀態 7 } 8 super.channelActive(ctx); 9 } 10 11 // 管道從活躍狀態 轉到 不活躍狀態 觸發 12 @Override 13 public void channelInactive(ChannelHandlerContext ctx) throws Exception { 14 15 Channel channel = ctx.channel(); 16 if(!channel.isOpen()){ 17 18 19 } 20 super.channelInactive(ctx); 21 }