Dubbo篇:基于Netty實(shí)現(xiàn)Dubbo協(xié)議編解碼源碼分析



Dubbo協(xié)議解析


?????????Dubbo協(xié)議設(shè)計(jì)參考了TCP/IP協(xié)議,包括協(xié)議頭和協(xié)議體兩部分晨横。16字節(jié)報(bào)文頭主要攜帶了魔法數(shù)(0xdabb莽囤,用于分割兩個(gè)不同請(qǐng)求),以及當(dāng)前請(qǐng)求報(bào)文是否是Request颗品、Response肯尺、心跳和事件的信息,請(qǐng)求時(shí)也會(huì)攜帶當(dāng)前報(bào)文體內(nèi)序列化協(xié)議編號(hào)躯枢,另外還有請(qǐng)求狀態(tài)则吟、請(qǐng)求唯一表示和報(bào)文體長(zhǎng)度。

在這里插入圖片描述

?????????0~7 ????????? 魔數(shù)高位 ??存儲(chǔ)0xda
?????????8~15 ????????魔數(shù)低位?? 存儲(chǔ)0xbb
?????????16???????????? 數(shù)據(jù)包類型?? 是否為雙向的RPC調(diào)用(比如方法調(diào)用有返回值)锄蹂,0位Response氓仲,1位Request
?????????17???????????? 調(diào)用方式 ?? 16位為1的情況下有效,0為單向調(diào)用得糜,1為雙向調(diào)用
?????????18???????????? 事件標(biāo)識(shí) ??? 0為請(qǐng)求/響應(yīng)包敬扛,1位心跳包
?????????19~23???????序列化器編號(hào)
?????????24~31???????狀態(tài)
?????????32~95?????? 請(qǐng)求編碼 ??? 8個(gè)字節(jié)存儲(chǔ)RPC請(qǐng)求的唯一id,用來將請(qǐng)求和響應(yīng)做關(guān)聯(lián)
?????????96~127?????消息體長(zhǎng)度 ??? 4個(gè)字節(jié)消息體朝抖,存有Dubbo版本號(hào)啥箭、服務(wù)接口名、服務(wù)接口版本治宣、方法名急侥、參數(shù)類型、方法參數(shù)值和請(qǐng)求額外參數(shù)



Netty編解碼器擴(kuò)展



?????????Netty提供了兩個(gè)基類炼七,一個(gè)是ByteToMessageDecoder解碼基類,一個(gè)是MessageToByteEncode編碼基類布持,用于自定義協(xié)議擴(kuò)展豌拙。


ByteToMessageDecoder



?????????ByteToMessageDecoder是一個(gè)抽象類,解碼方法名decode题暖,需要子類去實(shí)現(xiàn)按傅。繼承關(guān)系如下圖:

在這里插入圖片描述

?????????ByteToMessageDecoder繼承了ChannelInboundHandlerAdapter,是一個(gè)Inbound入站處理器胧卤,關(guān)于ChannelPipeline事件傳播機(jī)制前面幾篇文章已經(jīng)做了詳細(xì)介紹唯绍,此處不再贅述,所以重點(diǎn)關(guān)注一下其channelRead方法枝誊,即讀事件的傳播况芒,代碼如下:

在這里插入圖片描述

?????????其實(shí)現(xiàn)比較簡(jiǎn)單,主要是對(duì)ByteBuf解碼叶撒,然后繼續(xù)向下傳播ChannelRead事件绝骚,解碼具體實(shí)現(xiàn)在callDecode方法中,代碼實(shí)現(xiàn)如下:


在這里插入圖片描述

?????????callDecode中會(huì)讀取數(shù)據(jù)祠够,然后會(huì)調(diào)用decodeRemovalReentryProtection繼續(xù)解碼压汪,在decodeRemovalReentryProtection中我們看到了所期待的的調(diào)用子類的decode方法解碼。


MessageToByteEncoder


?????????與解碼器相對(duì)的古瓤,MessageToByteEncoder編碼器止剖,也是個(gè)抽象基類腺阳,提供了抽象方法encode需要子類去實(shí)現(xiàn),繼承關(guān)系如下圖:

在這里插入圖片描述

?????????由繼承關(guān)系圖可以看出穿香,MessageToByteEncoder繼承了ChannelOutboundHandlerAdapter亭引,是一個(gè)outbound出站處理器,重點(diǎn)關(guān)注其write方法扔水,代碼實(shí)現(xiàn)如下:

在這里插入圖片描述

?????????代碼邏輯還是比較清晰痛侍,就是調(diào)用encode編碼,然后向下傳播write事件魔市。

?????????到這里就看到了Netty對(duì)自定義編解碼的擴(kuò)展主届,下面介紹Dubbo對(duì)擴(kuò)展的自定義實(shí)現(xiàn)。



Dubbo協(xié)議實(shí)現(xiàn)源碼分析



?????????編解碼器本質(zhì)上都是handler待德,所以先從Netty啟動(dòng)是往ChannelPipeline中添加handler開始看君丁,以服務(wù)端為例,NettyServer#doOpen方法代碼如下:

在這里插入圖片描述

?????????標(biāo)準(zhǔn)的一個(gè)Netty服務(wù)器寫法将宪,里邊可以看到編解碼都由NettyCodecAdapter維護(hù)绘闷,NettyCodecAdapter代碼如下:

在這里插入圖片描述

?????????實(shí)現(xiàn)較為簡(jiǎn)單,維護(hù)了兩個(gè)內(nèi)部類较坛,一個(gè)是InternalEncoder繼承自MessageToByteEncoder印蔗,一個(gè)是InternalDecoder繼承自ByteToMessageDecoder,實(shí)現(xiàn)了對(duì)應(yīng)的編解碼接口丑勤。以及維護(hù)了一個(gè)Code2類型的對(duì)象华嘹,Codec2也是一個(gè)擴(kuò)展點(diǎn),對(duì)應(yīng)不同協(xié)議的實(shí)現(xiàn)法竞,因?yàn)榻榻BDubbo協(xié)議耙厚,所以此處是DubboCountCodec,DubboCountCodec代碼如下:


在這里插入圖片描述

?????????DubboCountCodec內(nèi)部維護(hù)了一個(gè)DubboCodec岔霸,DubboCodec才是編解碼具體實(shí)現(xiàn)薛躬,DubboCountCodec做的就是一次性讀取更多完整報(bào)文編解碼生成對(duì)象。DubboCodec繼承關(guān)系如下圖:

在這里插入圖片描述



encode源碼分析


?????????先介紹encode呆细,DubboCountCodec調(diào)用encode之后型宝,其具體實(shí)現(xiàn)邏輯位于ExchangeCodec#encode方法,實(shí)現(xiàn)代碼如下:

在這里插入圖片描述

?????????首先對(duì)需要編碼的消息類型進(jìn)行判斷絮爷,如果是Request則調(diào)用encodeRequest诡曙,如果是Response則調(diào)用encodeResponse,如果都不是略水,則調(diào)用父類TelnetCodec的encode方法价卤。先展開分析下encodeRequest方法,代碼如下:

在這里插入圖片描述

?????????實(shí)際上就是對(duì)開頭所描述的Dubbo協(xié)議的構(gòu)建渊涝,其中會(huì)調(diào)用encodeRequestData對(duì)RpcInvocation調(diào)用進(jìn)行編碼慎璧,代碼如下:

在這里插入圖片描述

?????????主要是將方法調(diào)用參數(shù)和值編碼成字節(jié)流床嫌。包括框架版本、調(diào)用接口胸私、方法名稱厌处、參數(shù)類型、參數(shù)值等信息岁疼。

?????????encodeResponse方法實(shí)現(xiàn)與encodeRequest方法實(shí)現(xiàn)十分相似阔涉,同樣是對(duì)Dubbo協(xié)議字節(jié)流的構(gòu)建,不再展開描述捷绒,主要介紹下其encodeResponseData方法瑰排,其data一半是Result類型,實(shí)現(xiàn)代碼如下:

在這里插入圖片描述

?????????主要完成對(duì)調(diào)用結(jié)果的序列化暖侨。




decode源碼分析


?????????解碼過程要比編碼復(fù)雜一點(diǎn)椭住,主要是需要解決粘包和半包問題,其實(shí)現(xiàn)位于ExchangeCodec#decode方法字逗,實(shí)現(xiàn)代碼如下:

在這里插入圖片描述

?????????解碼主要分為解碼16字節(jié)報(bào)文頭和解碼報(bào)文體京郑,具體的消息體解碼位于DubboCodec#decodeBody方法中,具體代碼如下:

在這里插入圖片描述

?????????解碼分為對(duì)request的解碼和response的解碼葫掉,雖然看上去很長(zhǎng)些举,其實(shí)只是請(qǐng)求類型的分類,以及根據(jù)decode.in.io的配置值判斷是在I/O線程中直接解碼俭厚,還是交由業(yè)務(wù)線程池去解碼户魏。

?????????請(qǐng)求消息解碼具體實(shí)現(xiàn)位于DecodeableRpcInvocation#decode方法,代碼實(shí)現(xiàn)如下:

在這里插入圖片描述

?????????主要邏輯是獲取各項(xiàng)參數(shù)封裝到當(dāng)前的RpcInvocation對(duì)象中套腹。

?????????響應(yīng)消息解碼的具體實(shí)現(xiàn)位于DecodeableRpcResult#decode中绪抛,具體代碼實(shí)現(xiàn)如下:

在這里插入圖片描述

?????????根據(jù)響應(yīng)標(biāo)記位资铡,對(duì)各種情況下的響應(yīng)做處理电禀,正常情況下將返回?cái)?shù)據(jù)反序列化后存到result字段中。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末笤休,一起剝皮案震驚了整個(gè)濱河市尖飞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌店雅,老刑警劉巖政基,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異闹啦,居然都是意外死亡沮明,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門窍奋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荐健,“玉大人酱畅,你說我怎么就攤上這事〗。” “怎么了纺酸?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)址否。 經(jīng)常有香客問我餐蔬,道長(zhǎng),這世上最難降的妖魔是什么佑附? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任樊诺,我火速辦了婚禮,結(jié)果婚禮上帮匾,老公的妹妹穿的比我還像新娘啄骇。我一直安慰自己,他們只是感情好瘟斜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布缸夹。 她就那樣靜靜地躺著,像睡著了一般螺句。 火紅的嫁衣襯著肌膚如雪虽惭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天蛇尚,我揣著相機(jī)與錄音芽唇,去河邊找鬼。 笑死取劫,一個(gè)胖子當(dāng)著我的面吹牛匆笤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谱邪,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼炮捧,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了惦银?” 一聲冷哼從身側(cè)響起咆课,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎扯俱,沒想到半個(gè)月后书蚪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡迅栅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年殊校,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片读存。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡为流,死狀恐怖窜醉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情艺谆,我是刑警寧澤榨惰,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站静汤,受9級(jí)特大地震影響琅催,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜虫给,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一藤抡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧抹估,春花似錦缠黍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至语泽,卻和暖如春贸典,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背踱卵。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工廊驼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惋砂。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓妒挎,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親西饵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子酝掩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355