Netty-鳥瞰

Netty-鳥瞰

  • Bootstrap:Netty應(yīng)用從構(gòu)建一個Bootstrap開始瞬浓,通過Bootstrap可以輕松的去配置并啟動應(yīng)用。

  • ChannelHandler:為了能夠提供多協(xié)議并且多樣的去處理數(shù)據(jù)磅叛,Netty使用handler回調(diào)對象去處理特定的事件(包括正常的數(shù)據(jù)傳輸事件以及異常的處理事件)。通常我們可以實現(xiàn)ChannelInboundHandler兆龙,這樣我們可以把我們具體的業(yè)務(wù)邏輯處理封裝在這個我們實現(xiàn)的handler中敲董。

  • ChannelInitializer:那我們怎么去綁定 ChannelHandler 去處理我們需要發(fā)送或者接收的消息呢紫皇?這里就用到ChannelInitializer,它的指責(zé)就是將 ChannelHandler 的實現(xiàn)加入到 ChannelPipeline坝橡。(事實上ChannelInitializer本身就是一個ChannelHandler精置,只不過這個handler會在加入其他handler的同時將自己從ChannelPipeline中移除)

  • ChannelPipeline: ChannelPipeline 和 EventLoop、EventLoopGroup相近都與事件和事件處理相關(guān)脂倦。

  • EventLoop & EventLoopGroup:指責(zé)在于處理通道中的IO操作,單個的 EventLoop 通常會處理多個通道上的事件赖阻。而 EventLoopGroup 包含了了多個 EventLoop ,并能用于去獲取 EventLoop棋电。

  • Channel:一個通道代表了一個 socket 鏈接,或者能夠進行IO處理的組件赶盔,因此這里用EventLoop來管理榆浓。

  • ChannelFuture: Netty中的IO操作都是異步的(包括連接、讀陡鹃、寫),這就意味著我們并不能知道操作是執(zhí)行成功是否返回闷叉,但是我們需要在后續(xù)的操作中執(zhí)行檢測或者注冊一些監(jiān)聽器來獲取通知。Netty使用 Futures 和 ChannelFutures 去注冊監(jiān)聽來獲取通知握侧。

    ChannelFuture是一個特殊的 java.util.concurrent.Future,它允許我們注冊 ChannnelFutureListeners 到ChannelFuture状知。這些listener會在操作執(zhí)行完成時得到通知。本質(zhì)上來說饥悴,ChannelFuture是操作執(zhí)行結(jié)果的占位符盲再。所有的操作都會返回一個 ChannelFuture。


EventLoop

Netty 是一個非阻塞的贷揽,事件驅(qū)動的網(wǎng)絡(luò)框架梦碗。初看,Netty是用多線程來處理IO事件的印屁。接觸過多線程編程的人可能會想雄人,在這樣需要同步我們的代碼。但事實上础钠,Netty的設(shè)計使我們不需要做過多的這些考慮叉谜。

EventLoop

如圖中所示正罢,Netty使用 EventLoopGroup 的組件里面有一個或者多個 EventLoop翻具。當(dāng)一個通道(Channel)被注冊進來,Netty會綁定這個通道到一個單獨的 EventLoop (當(dāng)然也是在一個單獨的線程中)裆泳,并且這個通道的生命周期只會與這一個 EventLoop 綁定工禾。這也就是為什么在我們的應(yīng)用在Netty框架下不需要做同步處理(所有的IO操作都是在給定的通道及同一個線程中)

EventLoop 總是被綁定到一個單獨的線程中,在其生命周期中絕不會更換線程闻葵。

EventLoop

如圖:EventLoop 和 EventLoopGroup 是一種 "is-a"關(guān)系

一個 EventLoop 就是一個 EventLoopGroup槽畔,這也就意味著我們在傳入一個 EventLoopGroup 的地方同樣也能指定一個 EventLoop。

BootStrap & ServeBootStrap

BootStrap:用于創(chuàng)建客戶端鳞尔;
ServerBootStrap:用于創(chuàng)建服務(wù)端寥假;

不同點一:

ServerBootStrap 綁定到一個端口去監(jiān)聽客戶端的鏈接霞扬;BootStrap 通常調(diào)用 connect() / bind(),然后在稍后使用 Channel (包含在ChannelFuture中)來進行連接喻圃。

不同點二:

客戶端 BootStrap 使用一個單獨的EventLoopGroup级及;然而,ServerBootStrap 使用兩個 EventLoopGroup (事實上使用同一個也是可以的)怕吴,第一個集合包含一個單獨的 ServerChannel 代表服務(wù)端自己的socket(這個socket被綁定到本地的一個端口上了)县踢,第二個集合包含所有的服務(wù)端接收的鏈接通道。

Two EventLoopGroup

如圖议经,EventLoopGroupA 唯一的目的是接收鏈接然后將它們交付到 EventLoopGroupB煞肾。

Netty這樣做的根本目的是為了客服鏈接瓶頸籍救。在一個高并發(fā)的場景下,可能會有極其多的鏈接接入蝙昙,當(dāng)只有一個Group時,處理已有鏈接已經(jīng)很繁忙败去,以至于無法接收新的鏈接烈拒,這最終會導(dǎo)致很多鏈接會超時。而使用兩個Group葫辐,接收鏈接和處理鏈接分開伴郁,這樣所有的鏈接都可以被接收。

EventLoopGroup 可能包含多個EventLoop(不過也取決與我們的具體配置)剂陡,每一個通道會有一個 EventLoop 與它綁定并且在整個生命周期內(nèi)都不會更換。不過鸭栖,由于 EventLoopGroup 中的 EventLoop 會比通道小晕鹊,所以會有很多通道共享一個 EventLoop,這也意味著在同一個 EventLoop 中溅话,一個通道處理繁忙的話飞几,將不允許去處理其他的通道屑墨,因此不要使用阻塞EventLoop的原因。

One EvetLoopGroup

如圖卵史,當(dāng)只有一個group時程腹,同一個實例會被使用兩次寸潦。

ChannelHandler

我們很容易想到 ChannelHandler 是用來處理數(shù)據(jù)流的,但是實際上 ChannelHandler 還能有很多其他的應(yīng)用见转。

ChannelHandler

如圖斩箫,從類繼承關(guān)系上可以看出乘客,我們有兩種 ChannelHandler淀歇,也反映出數(shù)據(jù)流是雙向的(數(shù)據(jù)可以從我們的應(yīng)用向外流出,也能從遠端流入我們的應(yīng)用)牡直。

數(shù)據(jù)從一段流到另一端的過程中碰逸,會經(jīng)過一個或者多個 ChannelHandler 的處理饵史。這個 ChannelHandler 會被加入到應(yīng)用中,并且它們加入的順序決定了它們處理數(shù)據(jù)的順序约急。

既然會設(shè)計到多個 ChannelHandler 協(xié)作厌蔽,必然會有一定的規(guī)則需要遵守摔癣。這里的規(guī)則很簡單:ChannelPipeline 就是這寫 ChannelHandler 的約束。每一個 ChannelHandler 處理完自己的部分后都會將數(shù)據(jù)傳遞到同一個 ChannelPipeline 中的下一個 ChannelHandler戴卜,直到?jīng)]有 ChannelHandler 為止琢岩。

ChannelPipeline

如圖:反映了 ChannelInboundHandler 和 ChannelOutboundHandler 能夠同時存在于一個 ChannelPipeline 中担孔。

由于我們的 ChannelHandler 通常實現(xiàn)自 ChannelInboundHandler 或 ChannelOutboundHandler 所以Netty會知道各個handler的類型吃警,這樣在一個流出的事件中就可以跳過所有的 ChannelInboundHandler酌心。

每一個加入 ChannelPipeline 中的 ChannelHandler 會得到一個 ChannelHandlerContext安券。通常獲得 ChannelHandlerContext 的引用是安全的侯勉,但是在 UDP 協(xié)議下可能不一定铝阐。 這個 ChannelHandlerContext 可以用于獲取底層的 channel 用于 write/send 消息。這樣就存在兩種方式來發(fā)送消息:直接寫到通道 或者 通過 ChannelHandlerContext 來寫消息饰迹,它們的主要區(qū)別是,直接寫到通道中的消息會從 ChannelPipeline 的尾部開始锹淌,寫到 ChannelHandlerContext 中的消息會傳遞給下一個handler

通過回調(diào)方法中攜帶的 ChannelHandlerContext 參數(shù)赠制,我們可以將一個事件可以定向到下一個 ChannelInboundHandler 或者 前一個 ChannelOutboundHandler 中钟些。(Netty為我們提供的抽象基類 ChannelInboundHandlerAdapter 和 ChannelOutboundHandlerAdapter 只提供單方向的傳遞政恍,但是我們不需要手動調(diào)用傳遞方法)

Encoder & Decoder

每一個通道都有傳遞Netty事件的職責(zé),Netty類中 *Adapter 結(jié)尾的類幫我們實現(xiàn)了這一過程迫筑,這樣我們不需要去關(guān)注這部分的工作宗弯,我們只需要去處理我們感興趣的部分脯燃。除了 *Adapter 的類外,同樣還有很多其他功能擴展的類我們可以使用蒙保,比如 encode/decode 消息辕棚。

當(dāng)我們接收到消息時,我們必須將其從 bytes 轉(zhuǎn)化成 Java對象。當(dāng)發(fā)送消息時逝嚎,我們同樣需要將消息從Java對象轉(zhuǎn)換成bytes扁瓢。這樣的操作很頻繁,因此Netty為我們提供了很多基礎(chǔ)類懈糯,類似于 ByteToMessageDecoder 和 MessageToByteEncoder 就提供這樣的功能涤妒。我們應(yīng)用中用的最多的可能是讀取消息并解碼然后再進行一系列的其他處理单雾,我們可以繼承 SimpleChannelInboundHandler<T> (T 就是我們要處理的消息類型)赚哗,這個handler的主要方法channelRead0(ChannelHandlerContext,T),不能何時調(diào)用該方法屿储,T 對象就是我們要處理的消息。

在IO線程中疯潭,不能進行阻塞的操作竖哩。Netty 允許在添加 ChannelHandler 到 ChannelPipeline 中時指定一個 EventExecutorGroup, 它會被用于獲取一個 EventExecutor 對象增淹,這個 EventExecutor 將用于執(zhí)行所有的ChannelHandler的操作(EventExecutor 會使用一個另外的線程)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子舞蔽,更是在濱河造成了極大的恐慌渗柿,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異门扇,居然都是意外死亡臼寄,警方通過查閱死者的電腦和手機质帅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門炼邀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來什猖,“玉大人不狮,你說我怎么就攤上這事∽そ觯” “怎么了噪服?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長丹墨。 經(jīng)常有香客問我,道長王财,這世上最難降的妖魔是什么狭握? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任哎垦,我火速辦了婚禮,結(jié)果婚禮上郑口,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好鹤耍,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布跌造。 她就那樣靜靜地躺著财著,像睡著了一般朝墩。 火紅的嫁衣襯著肌膚如雪愤兵。 梳的紋絲不亂的頭發(fā)上秆乳,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天肛冶,我揣著相機與錄音,去河邊找鬼馅笙。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的沥匈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了对蒲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鸣驱,失蹤者是張志新(化名)和其女友劉穎泛鸟,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡碑韵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了遗菠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辙纬。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡叭喜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涡匀,到底是詐尸還是另有隱情,我是刑警寧澤腕够,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站脸侥,受9級特大地震影響官边,放射性物質(zhì)發(fā)生泄漏诡渴。R本人自食惡果不足惜山上,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一婶恼、第九天 我趴在偏房一處隱蔽的房頂上張望荔泳。 院中可真熱鬧,春花似錦虐杯、人聲如沸玛歌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽支子。三九已至,卻和暖如春达舒,著一層夾襖步出監(jiān)牢的瞬間值朋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工巩搏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留昨登,地道東北人。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓贯底,卻偏偏與公主長得像丰辣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子丈甸,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容