前言:
Netty是一個非同步事件驅動的網路應用程式框架用於快速開發可維護的高效能協議伺服器和客戶端。
特點:
統一的API,適用於不同的協議(阻塞和非阻塞)
基於靈活、可擴充套件的事件驅動模型
高度可定製的執行緒模型
拉取 https://github.com/netty/netty/tree/3.9
命令:
git clone https://github.com/netty/netty.gitGit checkout -b 3.9 origin/3.9
Git checkout -b 3.9 origin/3.9
複製程式碼
netty概覽:
在netty中,Channel是通訊的載體,ChannelHandler是資料處理的執行者,ChannelPipeline是資料處理的通道;
資料流向分析:
以DefaultChannelPipeline為例,講述已註冊到管道pipeline的ChannelHandler如何處理資料?
downStream方向 :業務物件 =》 資料流
從pipeline管道tail物件起依次呼叫註冊的ChannelDownstreamHandler處理器,最終經由ChannelSink的eventSunk根據事件觸發boss或者worker執行緒池處理任務。
upStream方向 :資料流 =》 業務物件
從pipeline管道head物件開始依次呼叫註冊的ChannelUpstreamHandler處理器,最終將資料流轉為業務層的業務物件。
這點很重要,會影響到我們註冊處理器的邏輯。
對於ChannelSink如何真正地觸發資料寫出去?暫僅考慮MessageEvent,可以看到將訊息寫到channel所在worker執行緒的佇列中,並呼叫writeFromUserCode觸發worker傳送資料。
寫模型:
對於存在佇列中的資料如何依次傳送呢?如果不可寫了該怎麼處理?(寫入過快來不及傳送,導致緩衝區滿了)
可以看到依次處理佇列中的訊息,如果有訊息,則呼叫buf.transferTo(ch)將資料傳送出去,如果返回localWrittenBytes大於0,跳出本次迴圈,如為零則迴圈writeSpinCount,如再次期間localWrittenBytes>0,說明再次可寫。並呼叫fireWriteComplete觸發上游,這裡暫時忽略結果處理。
說明:觸發寫不止這種情況,channel可寫的情況下也會觸發將佇列清空。
讀模型分析:
寫的流程已經分析完成,讀模型相對簡單,當監聽到讀事件時,即會觸發worker讀取資料裝載成buffer,呼叫handler處理。
後續:
後續會先對Netty特性基於原始碼分析,並設計個便捷可配置的壓測模型,方便開發中快速針對不同通訊實現壓測。
可以點選閱讀原文獲取《Nip trick and trip》,相信可以使得netty的理解更深入。
喜歡的讀者可以關注路上小棧,及時獲取最新的技術文章,專注原始碼分析、技術業務思考等。