1. 判斷目前Handelr是否能處理寫入的消息(比對對象)

判斷該對象是否是該類型參數比對器執行個體可比對到的類型
2 配置設定記憶體
3 編碼實作
- 調用
,這裡就調回到encode
這個Encoder
中Handler
- 其為抽象方法,是以自定義實作類實作編碼方法
4 釋放對象
- 既然自定義Java對象轉換成
了,那麼這個對象就已經無用,釋放掉 (當傳入的ByteBuf
類型是msg
時,就不需要自己手動釋放了)ByteBuf
5 傳播資料
//112 如果buf中寫入了資料,就把buf傳到下一個節點,直到 header 節點
6 釋放記憶體
//115 否則,釋放buf,将空資料傳到下一個節點
// 120 如果目前節點不能處理傳入的對象,直接扔給下一個節點處理
// 127 當buf在pipeline中處理完之後,釋放
Encoder處理傳入的Java對象
- 判斷目前Handler是否能處理寫入的消息
- 如果能處理,進入下面的流程
- 否則,直接扔給下一個節點處理
- 将對象強制轉換成Encoder 可以處理的 Response對象
- 配置設定一個ByteBuf
- 調用encoder,即進入到 Encoder 的 encode方法,該方法是使用者代碼,使用者将資料寫入ByteBuf
- 既然自定義Java對象轉換成ByteBuf了,那麼這個對象就已經無用了,釋放掉(當傳入的msg類型是ByteBuf時,無需自己手動釋放)
- 如果buf中寫入了資料,就把buf傳到下一個節點,否則,釋放buf,将空資料傳到下一個節點
- 最後,當buf在pipeline中處理完之後,釋放節點
總結就是,
Encoder
節點配置設定一個
ByteBuf
,調用
encode
方法,将Java對象根據自定義協定寫入到ByteBuf,然後再把ByteBuf傳入到下一個節點,在我們的例子中,最終會傳入到head節點
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
unsafe.write(msg, promise);
}
這裡的msg就是前面在Encoder節點中,載有java對象資料的自定義ByteBuf對象
write - 寫buffer隊列
Netty 源碼深度解析(九) - 編碼(中)
以下過程分三步講解
direct ByteBuf
- 首先,調用
確定該方法的調用是在assertEventLoop
線程中reactor
- 然後,調用
,将待寫入的對象過濾,把非filterOutboundMessage()
對象和ByteBuf
過濾,把所有的非直接記憶體轉換成直接記憶體FileRegion
DirectBuffer
Netty 源碼深度解析(九) - 編碼(中)
插入寫隊列
- 接下來,估算出需要寫入的ByteBuf的size
- 最後,調用 ChannelOutboundBuffer 的addMessage(msg, size, promise) 方法,是以,接下來,我們需要重點看一下這個方法幹了什麼事情
想要了解上面這段代碼,須掌握寫緩存中的幾個消息指針
ChannelOutboundBuffer 裡面的資料結構是一個單連結清單結構,每個節點是一個 Entry,Entry 裡面包含了待寫出ByteBuf 以及消息回調 promise下面分别是
三個指針的作用
- flushedEntry
表第一個被寫到OS Socket緩沖區中的節點
- unFlushedEntry
表第一個未被寫入到OS Socket緩沖區中的節點
- tailEntry
表
ChannelOutboundBuffer
緩沖區的最後一個節點
圖解過程
- 初次調用write 即
後addMessage
- 第二次調用
後addMessage
- 第n次調用
addMessage
可得,調用n次
addMessage
-
指針一直指向flushedEntry
,表此時尚未有節點需寫到Socket緩沖區null
-
後有n個節點,表目前還有n個節點尚未寫到Socket緩沖區unFushedEntry