dubbo協(xié)議詳解

協(xié)議的概念:

????????協(xié)議是兩個網(wǎng)絡(luò)實體進(jìn)行通信的基礎(chǔ)侨艾,數(shù)據(jù)在網(wǎng)絡(luò)上從一個實體傳輸?shù)搅硪粋€實體捣染,以字節(jié)流的形式傳遞到對端漾稀。在這個字節(jié)流的世界里描沟,如果沒有協(xié)議预愤,就無法將這個一維的字節(jié)流重塑成為二維或者多維的數(shù)據(jù)結(jié)構(gòu)以及領(lǐng)域?qū)ο蟆?/p>

協(xié)議是什么?

????????協(xié)議是雙方確定的交流語義眼五,比如:我們設(shè)計一個字符串傳輸?shù)膮f(xié)議妆艘,它允許客戶端發(fā)送一個字符串,服務(wù)端接收到對應(yīng)的字符串看幼。這個協(xié)議很簡單批旺,首先發(fā)送一個4字節(jié)的消息總長度,然后再發(fā)送1字節(jié)的字符集charset長度桌吃,接下來就是消息的payload(載量)朱沃,字符集名稱和字符串正文。

發(fā)送一個iso-8859-1的字符串a(chǎn)bc到對端茅诱。經(jīng)過協(xié)議編碼逗物,內(nèi)容是:18 = 4 + 1 + 10 + 3|10|iso-8859-1|abc,當(dāng)這些字節(jié)流發(fā)往服務(wù)端后瑟俭,當(dāng)服務(wù)端收到字節(jié)流后翎卓,首先讀取4個字節(jié),將其轉(zhuǎn)換為int摆寄,在這個例子中是18失暴,接下來繼續(xù)讀14個字節(jié)坯门,將首個字節(jié)得到字符集名稱長度10,將后續(xù)內(nèi)容的前10字節(jié)轉(zhuǎn)換為字符串逗扒,內(nèi)容是iso-8859-1古戴,使用該字符集將后續(xù)的字節(jié)數(shù)組造型成為字符串new String(bytes, "iso-8859-1")。

在前面自定義字符串傳輸協(xié)議的例子中矩肩,我們已經(jīng)看到協(xié)議在雙方傳輸數(shù)據(jù)中起到的作用现恼,沒有協(xié)議就無法完成數(shù)據(jù)交換,下面是維基百科對于通信協(xié)議的定義:

In telecommunication, a communication protocol is a system of rules that allow two or more entities of a communications system to transmit information via any kind of variation of a physical quantity. The protocol defines the rules syntax, semantics and synchronization of communication and possible error recovery methods. Protocols may be implemented by hardware, software, or a combination of both.

在電信技術(shù)中黍檩,通信協(xié)議是允許通信系統(tǒng)中的兩個或多個實體通過物理量的任何變化來傳輸信息的規(guī)則系統(tǒng)叉袍。該協(xié)議定義了通信的語法、語義和同步規(guī)則以及可能的錯誤恢復(fù)方法刽酱。協(xié)議可以通過硬件喳逛、軟件或兩者的組合來實現(xiàn)。

可以看到通信協(xié)議需要定義語法棵里、語義以及通信上的同步操作润文,這里描述的內(nèi)容實際就是對前面自定義字符串傳輸協(xié)議的形式化描述。

Codec(編解碼器)的定義:

org.apache.dubbo.remoting.Codec2定義為I/O的?Codec?過程殿怜,因此主要的方法就是encode和decode转唉,具體定義如下所示:

?Codec工作在一種協(xié)議上,encode是將通信對象編碼到ByteBufferWrapper中稳捆,decode是將從網(wǎng)絡(luò)上讀取的ChannelBuffer解碼為Object,也就是通信對象麦轰。


常見的協(xié)議模式:

應(yīng)用層協(xié)議一般的形式有三種:定長協(xié)議乔夯、特殊結(jié)束符和協(xié)議頭+payload模式,下面介紹一下這些形式的具體內(nèi)容款侵。

從網(wǎng)絡(luò)上以流的形式進(jìn)行數(shù)據(jù)的讀取末荐,需要確定的是一次有意義的傳輸內(nèi)容在讀到何時結(jié)束,因為一個一個byte傳輸過來新锈,需要有一個結(jié)束甲脏。而且數(shù)據(jù)在網(wǎng)絡(luò)上的傳輸,存在粘包和半包的情況妹笆,能夠應(yīng)對這個問題的辦法就是協(xié)議能夠準(zhǔn)確的識別块请,當(dāng)粘包發(fā)生時不會多讀,當(dāng)半包發(fā)生時會繼續(xù)讀取拳缠。

1墩新、定長協(xié)議:定長的協(xié)議是指協(xié)議內(nèi)容的長度是固定的,比如協(xié)議byte長度是50窟坐,當(dāng)從網(wǎng)絡(luò)上讀取50個byte后海渊,就進(jìn)行decode解碼操作绵疲。定長協(xié)議在讀取或者寫入時,效率比較高臣疑,因為數(shù)據(jù)緩存的大小基本都確定了盔憨,就好比數(shù)組一樣,缺陷就是適應(yīng)性不足讯沈,以RPC場景為例郁岩,很難估計出定長的長度是多少。

可以參考Netty的FixedLengthFrameDecoder

2芙盘、特殊結(jié)束符:相比定長協(xié)議驯用,如果能夠定義一個特殊字符作為每個協(xié)議單元結(jié)束的標(biāo)示,就能夠以變長的方式進(jìn)行通信儒老,從而在數(shù)據(jù)傳輸和高效之間取得平衡蝴乔,比如用特殊字符\n。

特殊結(jié)束符方式的問題是過于簡單的思考了協(xié)議傳輸?shù)倪^程驮樊,對于一個協(xié)議單元必須要全部讀入才能夠進(jìn)行處理薇正,除此之外必須要防止用戶傳輸?shù)臄?shù)據(jù)不能同結(jié)束符相同,否則就會出現(xiàn)紊亂囚衔。

可以參考Netty的DelimiterBasedFrameDecoder

3挖腰、變長協(xié)議(協(xié)議頭+payload):一般是自定義協(xié)議,會以定長加不定長的部分組成练湿,其中定長的部分需要描述不定長的內(nèi)容長度猴仑。

可以參考Netty的LengthFieldBasedFrameDecoder

Dubbo 協(xié)議實際上就是一種變長協(xié)議,后面的章節(jié)會詳細(xì)介紹肥哎。


Dubbo協(xié)議:

1辽俗、協(xié)議概覽:Dubbo 框架定義了私有的RPC協(xié)議,其中請求和響應(yīng)協(xié)議的具體內(nèi)容我們使用表格來展示篡诽。

2崖飘、協(xié)議詳情:

①:Magic - Magic High & Magic Low (16 bits)

? ? ? 標(biāo)識協(xié)議版本號,Dubbo 協(xié)議:0xdabb

②:Req/Res (1 bit)

? ? ? 標(biāo)識是請求或響應(yīng)杈女。請求: 1; 響應(yīng): 0朱浴。

③:2 Way (1 bit)?

? ? ? 僅在 Req/Res 為1(請求)時才有用,標(biāo)記是否期望從服務(wù)器返回值达椰。如果需要來自服務(wù)器的返回值翰蠢,則設(shè)置為1。

④:Event (1 bit)

? ? ? 否是事件消息啰劲,例如躏筏,心跳事件。如果這是一個事件呈枉,則設(shè)置為1趁尼。

⑤:Serialization ID (5 bit)?

? ? ? 標(biāo)識序列化類型:比如 fastjson 的值為6埃碱。

⑥:Status (8 bits)

? ? ? 僅在 Req/Res 為0(響應(yīng))時有用,用于標(biāo)識響應(yīng)的狀態(tài)酥泞。

????????????○20 - OK

????????????○30 - CLIENT_TIMEOUT

????????????○31 - SERVER_TIMEOUT

????????????○40 - BAD_REQUEST

????????????○50 - BAD_RESPONSE

????????????○60 - SERVICE_NOT_FOUND

????????????○70 - SERVICE_ERROR

????????????○80 - SERVER_ERROR

????????????○90 - CLIENT_ERROR

????????????○100 - SERVER_THREADPOOL_EXHAUSTED_ERROR

⑦:Request ID (64 bits)?

? ? ? 標(biāo)識唯一請求砚殿。類型為long。

⑧:Data Length (32 bits)

? ? ? 序列化后的內(nèi)容長度(可變部分)芝囤,按字節(jié)計數(shù)似炎。int類型。

⑨:Variable Part(可變部分)

? ? ? 被特定的序列化類型(由序列化 ID 標(biāo)識)序列化后悯姊,每個部分都是一個 byte [] 或者 byte? ? ?

?? ? ? ? ○如果是請求包 ( Req/Res = 1)羡藐,則每個部分依次為:

????????????????????●Dubbo version

????????????????????●Service name

????????????????????●Service version

????????????????????●Method name

????????????????????●Method parameter types

????????????????????●Method arguments

????????????????????●Attachments

? ? ? ? ? ○如果是響應(yīng)包(Req/Res = 0),則每個部分依次為:

????????????????????●返回值類型(byte)悯许,標(biāo)識從服務(wù)器端返回的值類型:

????????????????????????????●返回空值:RESPONSE_NULL_VALUE 2

????????????????????????????●正常響應(yīng)值: RESPONSE_VALUE 1

????????????????????????????●異常:RESPONSE_WITH_EXCEPTION 0

????????????????????●返回值:從服務(wù)端返回的響應(yīng)bytes

注意:?對于(Variable Part)變長部分仆嗦,當(dāng)前版本的Dubbo 框架使用json序列化時,在每部分內(nèi)容間額外增加了換行符作為分隔先壕,請在Variable Part的每個part后額外增加換行符瘩扼, 如:

Dubbo version bytes (換行符)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Service name bytes? (換行符)?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ...

Dubbo 協(xié)議的優(yōu)缺點:

優(yōu)點:

○協(xié)議設(shè)計上很緊湊,能用 1 個 bit 表示的垃僚,不會用一個 byte 來表示集绰,比如 boolean 類型的標(biāo)識。

○請求谆棺、響應(yīng)的 header 一致栽燕,通過序列化器對 content 組裝特定的內(nèi)容,代碼實現(xiàn)起來簡單改淑。

可以改進(jìn)的點:

○類似于 http 請求纫谅,通過 header 就可以確定要訪問的資源,而 Dubbo 需要涉及到用特定序列化協(xié)議才可以將服務(wù)名溅固、方法、方法簽名解析出來兰珍,并且這些資源定位符是 string 類型或者 string 數(shù)組侍郭,很容易轉(zhuǎn)成 bytes,因此可以組裝到 header 中掠河。類似于 http2 的 header 壓縮亮元,對于 rpc 調(diào)用的資源也可以協(xié)商出來一個int來標(biāo)識,從而提升性能唠摹,如果在header上組裝資源定位符的話爆捞,該功能則更易實現(xiàn)。

○通過 req/res 是否是請求后勾拉,可以精細(xì)定制協(xié)議煮甥,去掉一些不需要的標(biāo)識和添加一些特定的標(biāo)識盗温。比如status,twoWay標(biāo)識可以嚴(yán)格定制,去掉冗余標(biāo)識成肘。還有超時時間是作為 Dubbo 的?attachment?進(jìn)行傳輸?shù)穆艟郑碚撋蠎?yīng)該放到請求協(xié)議的header中,因為超時是網(wǎng)絡(luò)請求中必不可少的双霍。提到?attachment?砚偶,通過實現(xiàn)可以看到?attachment?中有一些是跟協(xié)議?content中已有的字段是重復(fù)的,比如?path和version等字段洒闸,這些會增大協(xié)議尺寸染坯。

○Dubbo 會將服務(wù)名 com.alibaba.middleware.hsf.guide.api.param.ModifyOrderPriceParam ,轉(zhuǎn)換為? Lcom/alibaba/middleware/hsf/guide/api/param/ModifyOrderPriceParam;? 丘逸,理論上是不必要的单鹿,最后追加一個? ;? 即可。

○Dubbo 協(xié)議沒有預(yù)留擴展字段鸣个,沒法新增標(biāo)識羞反,擴展性不太好,比如新增響應(yīng)上下文的功能囤萤,只有改協(xié)議版本號的方式昼窗,但是這樣要求客戶端和服務(wù)端的版本都進(jìn)行升級,對于分布式場景很不友好涛舍。

總結(jié):

本文主要介紹了協(xié)議的概念和常用的協(xié)議模式澄惊,后面對 Dubbo 協(xié)議進(jìn)行了詳細(xì)分析,也提到了一些不足的地方富雅,但是相對于其簡潔性和易于實現(xiàn)性掸驱,以上提出的缺點不足以有動力設(shè)計出一個新版本的協(xié)議,所以歡迎大家提出對協(xié)議優(yōu)化方面的建議和特性没佑。

文章來源:Dubbo 協(xié)議詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毕贼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蛤奢,更是在濱河造成了極大的恐慌鬼癣,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啤贩,死亡現(xiàn)場離奇詭異待秃,居然都是意外死亡,警方通過查閱死者的電腦和手機痹屹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門章郁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人志衍,你說我怎么就攤上這事暖庄×奶妫” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵雄驹,是天一觀的道長佃牛。 經(jīng)常有香客問我,道長医舆,這世上最難降的妖魔是什么俘侠? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮蔬将,結(jié)果婚禮上爷速,老公的妹妹穿的比我還像新娘。我一直安慰自己霞怀,他們只是感情好惫东,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著毙石,像睡著了一般廉沮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上徐矩,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天滞时,我揣著相機與錄音,去河邊找鬼滤灯。 笑死坪稽,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鳞骤。 我是一名探鬼主播窒百,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼豫尽!你這毒婦竟也來了篙梢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤美旧,失蹤者是張志新(化名)和其女友劉穎渤滞,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體陈症,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年震糖,在試婚紗的時候發(fā)現(xiàn)自己被綠了录肯。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡吊说,死狀恐怖论咏,靈堂內(nèi)的尸體忽然破棺而出优炬,到底是詐尸還是另有隱情,我是刑警寧澤厅贪,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布蠢护,位于F島的核電站,受9級特大地震影響养涮,放射性物質(zhì)發(fā)生泄漏葵硕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一贯吓、第九天 我趴在偏房一處隱蔽的房頂上張望懈凹。 院中可真熱鬧,春花似錦悄谐、人聲如沸介评。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽们陆。三九已至,卻和暖如春情屹,著一層夾襖步出監(jiān)牢的瞬間坪仇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工屁商, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留烟很,地道東北人。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓蜡镶,卻偏偏與公主長得像雾袱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子官还,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355