1. 程式人生 > >圖解Netty之Pipeline、channel、Context之間的資料流向。

圖解Netty之Pipeline、channel、Context之間的資料流向。

   以下所繪製圖形均基於Netty4.0.28版本。

一、connect(outbound型別事件)

     當用戶呼叫channel的connect時,會發起一個outbound型別的事件,該事件將在pipeline中傳遞(pipeline.connect),首先由tail handler處理,該handler只是將事件透傳給下一個outbound型別的使用者Handler(如果有),事件依次傳遞下去,直到傳遞到head handler,該handler會呼叫unsafe.connect()向eventloop(nio的selector)註冊一個讀事件。 

 二、connect成功之後資料流圖(inbound型別事件)

      當用戶發起一個connect請求後,當連線可用時,eventloop(底層使用nio的selector)會引發一個ChannelActive事件,該事件最先有unsafe捕獲,之後會呼叫pipeline.fireChannelActive()將該事件在pipeline中傳播,緊接著會根據inbound型別事件的傳遞方式在各個handler和context之間進行鏈式傳遞。其中,有一個比較關注的地方是,在channelActive事件觸發的時候,如果channel被設定成autoRead,那麼此時還會呼叫channel.read()方法,該方法並不是真正的從channel讀取資料,而是向eventloop註冊讀事件(因為一個channel在向eventloop中註冊時,預設不註冊任何事件),關於channel.read的過程可以看下文的另一張圖。

三、channel.read事件流圖(outbound型別事件)

      當用戶呼叫channel.read()後,會發起一個outbound型別的事件,該事件最先會由pipeline中tail handler處理,該handler只是將該事件透傳給前面一個outbound型別的使用者handler(如果有的話),這樣依次繼續向前傳遞,直到傳遞到head handler,該handler會呼叫unsafe.read()向eventloop註冊讀事件(也就是向nio的selector上新增讀事件)

四、channel.write(outbound型別事件)

     與channel.read()型別,wirte也是一個outbound型別事件,該事件最先會由pipeline中的tail handler透傳給前面的一個outbound型別的使用者handler(如果有的話),這樣依次傳遞,直到傳遞給head handler,該handler會呼叫unsafe.write()方法,這裡的wirte並不會執行真正的傳送,而是將要傳送的資料快取起來,直到呼叫flush時,這些資料才會執行真正的網路io。 

 五、flush(outbound型別事件)

     如前文所示,flush也是一個outbound型別的事件,與wirte不同,flush會執行真正的網路io操作。

六、當channel有資料可讀時(inbound型別事件)

     當eventloop層檢測到網路層有資料可讀時(nio的selector返回相應的seleciontKeys),該事件會首先傳遞給unsafe,緊接著會呼叫pipeline.fireChannelRead(),將事件開始在pipeline中傳遞,該事件最先會有head handler處理(head.fireChannelRead()),該handler直接將事件透傳給下一個inbound型別的使用者handler(如果有的話),該事件依次向下傳遞,直到傳遞到tail handler。

https://www.cnblogs.com/chenyangyao/p/netty.html?utm_source=itdadao&utm_medium=referral