聲明:本文為原創博文,禁止轉載。
以下所繪制圖形均基於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。