RPC-Thrift協(xié)議

一、序列化協(xié)議

? ? ? ?Thrift可以讓你選擇客戶端與服務(wù)端之間傳輸通信協(xié)議的類別,在傳輸協(xié)議上總體上劃分為文本(text)和二進(jìn)制(binary)傳輸協(xié)議, 為節(jié)約帶寬宛琅,提供傳輸效率,一般情況下使用二進(jìn)制類型的傳輸協(xié)議為多數(shù),但有時(shí)會(huì)還是會(huì)使用基于文本類型的協(xié)議任连,這需要根據(jù)項(xiàng)目/產(chǎn)品中的實(shí)際需求(例如:調(diào)試的時(shí)候)。

序列化協(xié)議類型:

TBinaryProtocol:二進(jìn)制編碼格式進(jìn)行數(shù)據(jù)傳輸例诀。

TCompactProtocol:高效密集型的二進(jìn)制序列化協(xié)議随抠,使用Variable-Length Quantity (VLQ) 編碼對數(shù)據(jù)進(jìn)行壓縮。

TJSONProtocol:使用JSON的數(shù)據(jù)編碼協(xié)議進(jìn)行數(shù)據(jù)傳輸繁涂。

TSimpleJSONProtocol:這種節(jié)約只提供JSON只寫的協(xié)議拱她,適用于通過腳本語言解析。

TTupleProtocol(繼承自TCompactProtocol)

TDebugProtocol:在開發(fā)的過程中幫助開發(fā)人員調(diào)試用的扔罪,以文本的形式展現(xiàn)方便閱讀秉沼。

RPC框架中一般使用 TCompactProtocol。

二矿酵、傳輸層

Thrift中所有的傳輸層協(xié)議的基類是TTransport唬复。另外,需要說明的一點(diǎn)是全肮,thrift是基于TCP協(xié)議的敞咧。

傳輸協(xié)議類型:

TSocket:使用堵塞式I/O進(jìn)行傳輸,也是最常見的模式倔矾。

TFramedTransport:使用非阻塞方式妄均,以frame為單位進(jìn)行傳輸,類似于Java中的NIO哪自。

TFileTransport:以文件形式進(jìn)行傳輸丰包,雖然這種方式不提供Java的實(shí)現(xiàn),但是實(shí)現(xiàn)起來非常簡單壤巷。

TMemoryTransport:使用內(nèi)存I/O邑彪,如Java中的ByteArrayOutputStream實(shí)現(xiàn)。

TZlibTransport:使用執(zhí)行zlib壓縮胧华,與其他傳輸方式聯(lián)合使用寄症,不提供Java的實(shí)現(xiàn)。

TNonblockingTransport:使用非阻塞方式矩动,用于構(gòu)建異步客戶端有巧。

RPC框架中一般使用 TFramedTransport。

三悲没、Thrift的序列化和反序列化方式

步驟:

使用IDL創(chuàng)建thrift接口定義文件篮迎;

將thrift的定義文件轉(zhuǎn)換為對應(yīng)語言的源代碼;

選擇相應(yīng)的protocol,進(jìn)行序列化和反序列化甜橱;

四逊笆、TCompactProtocol與TBinaryProtocol的原理和區(qū)別

Thrift二進(jìn)制序列化協(xié)議中,默認(rèn)為TBinaryProtocol岂傲,關(guān)于TCompactProtocol的說明难裆,為高效密集型的二進(jìn)制序列化(varint)。

那么TCompactProtocol相對于TBinaryProtocol是怎樣做到高效密集的呢镊掖?TCompactProtocol是否一定比TBinaryProtocol高效乃戈?

我們以比較常用的i32類型為例,來解釋一下兩種方式各自的原理:

TBinaryProtocol

處理i32整型數(shù)據(jù)類型時(shí)亩进,定義的是4個(gè)字節(jié)的數(shù)組偏化,32位的長度正好可以保存到這4個(gè)字節(jié)組當(dāng)中。如果我們分別以n1~n32來表示第1位到第32位镐侯,那么這個(gè)數(shù)組的數(shù)據(jù)結(jié)構(gòu)應(yīng)該為以下結(jié)構(gòu):

i32out[0] {n1 ?~ n8 }

i32out[1] {n9 ?~ n16}

i32out[2] {n17 ~ n24}

i32out[3] {n25 ~ n32}

這樣的實(shí)現(xiàn)很簡單.

對于其它類型,比如i16驶冒,也是類似的原理苟翻,不過是以2個(gè)字節(jié)的數(shù)組保存,在此不再說明了骗污。

因?yàn)槲覀兗軜?gòu)中使用的是TCompactProtocol崇猫,所以我們需要重點(diǎn)了解一下該協(xié)議的序列化方式。

TCompactProtocol

在處理i32整型數(shù)據(jù)類型時(shí)需忿,與TBinaryProtocol完全不同诅炉,采用的是1~5個(gè)字節(jié)組來保存。依然以n1~n32來表示第1位到第32位屋厘,數(shù)據(jù)結(jié)構(gòu)應(yīng)該為以下結(jié)構(gòu):

i32out[0] {1 , 0 , 0 , 0 , n1 ~ n4}

i32out[1] {1 , n5 ~ n11}

i32out[2] {1 , n12 ~ n18}

i32out[3] {1 , n19 ?~ n25}

i32out[4] {0?, n26 ?~ n32}

這是一種極端情況涕烧,5個(gè)字節(jié)全部占滿。

很顯然,這樣做比TBinaryProtocol復(fù)雜得多汗洒,而且還多了1個(gè)字節(jié)议纯,并沒有達(dá)到密集的目的。那是不是說明TBinaryProtocol更好?

先不急著下結(jié)論溢谤,舉個(gè)具體一點(diǎn)的例子來說明兩種實(shí)現(xiàn)的區(qū)別瞻凤。

假如我們需要序列化一個(gè)十進(jìn)制數(shù)值'10',那么它的二進(jìn)制表示方式應(yīng)該為'1010'世杀,只用了4位阀参,但i32會(huì)在前面自動(dòng)補(bǔ)0,

則是:'00000000000000000000000000001010'瞻坝,那么如果使用TBinaryProtocol方式來保存蛛壳,則應(yīng)該為以下結(jié)構(gòu):

i32out[0] {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0}

i32out[1] {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0}

i32out[2] {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0}

i32out[3] {0 , 0 , 0 , 0 , 1 , 0 , 1 , 0}

這樣有什么問題呢?那就是大量補(bǔ)足的0占用了寶貴空間。

接著我們再來看看TCompactProtocol會(huì)怎樣保存'10'這個(gè)數(shù)值:

i32out[0] {0 , 0 , 0 , 0 , 1 , 0 , 1 , 0}

TCompactProtocol只用了1個(gè)字節(jié)炕吸,而TBinaryProtocol依然用了4個(gè)字節(jié)伐憾。這就是為什么說TCompactProtocol高效密集型的二進(jìn)制序列化的原因。

TCompactProtocol的保存規(guī)則

TCompactProtocol每個(gè)字節(jié)的第1位是狀態(tài)位赫模,第2位到第8位保存具體的數(shù)據(jù).

這有別于TBinaryProtocol的1到8位全部保存具體數(shù)據(jù)树肃。這也是為什么極端情況下TCompactProtocol比TBinaryProtocol多占1個(gè)字節(jié)的原因。

TCompactProtocol的字節(jié)中第1位狀態(tài)位的意思是標(biāo)記此字節(jié)后是否還有數(shù)據(jù)瀑罗。1為有數(shù)據(jù)胸嘴,0為沒有數(shù)據(jù).

為了更容易理解,我們再舉一個(gè)例子,用TCompactProtocol來序列化十進(jìn)制數(shù)值'300'斩祭,二進(jìn)制應(yīng)該為'100101100'劣像,用TCompactProtocol方式來保存則為如下結(jié)構(gòu):

i32out[0] {1 , 0 , 0 , 0 , 0 , 0 , 1 , 0}

i32out[1] {0 , 0 , 1 , 0 , 1 , 1 , 0 , 0}

這里將'100101100'拆分為了2部分,'10'和'0101100',在i32out[0]中保存了'10'摧玫,并在第1位記為'1'來表示后面還有數(shù)據(jù)耳奕,第7位和第8位保存'10',不足的幾位(第2位到第6位)補(bǔ)0诬像;

所以i32out[0]為'10000010'屋群,在i32out[1]中保存了后面的'0101100',并在第1位記為'0'來表示后面沒有了坏挠,則第1位為'0'芍躏,所以i32out[1]為'00101100'。

TCompactProtocol以這樣的原理來達(dá)到壓縮的目的降狠。


thrift 文件:

namespace java mmxf.thrift;

struct Pair {

  1: required string key

  2: required string value

}

"1", "2" 這些數(shù)字標(biāo)識(shí)符究竟有何含義? 它在序列化機(jī)制中究竟扮演什么樣的角色?

thrift官網(wǎng)描述:thrift的向后兼容性(Version)借助屬性標(biāo)識(shí)(數(shù)字編號(hào)id + 屬性類型type)來實(shí)現(xiàn), 可以理解為在序列化后(屬性數(shù)據(jù)存儲(chǔ)由?field_name:field_value => id+type:field_value)对竣。

所以,id很重要榜配,一旦id順序混淆或者有變化否纬,value值與name的對應(yīng)也會(huì)變換,name在其中并沒有映射作用芥牌。

注意:RPC服務(wù)數(shù)據(jù)發(fā)送方(生產(chǎn)者)和讀取方(消費(fèi)者)如果同樣的字段name烦味,id不同,獲取到的value是不一致的壁拉,會(huì)出現(xiàn)不同name的value互換的奇怪現(xiàn)象谬俄。

數(shù)據(jù)交換格式分類

當(dāng)前的數(shù)據(jù)交換格式可以分為如下幾類:

1. 自解析型

序列化的數(shù)據(jù)包含完整的結(jié)構(gòu),包含了field名稱和value值. 比如xml/json/java serizable弃理,百度的mcpack/compack, 都屬于此類. 即調(diào)整不同屬性的順序?qū)π蛄谢?反序列化不影響溃论。

2. 半解析型

? ? ? ? 序列化的數(shù)據(jù),丟棄了部分信息,比如field名稱痘昌,但引入了index(常常是id+type的方式)來對應(yīng)具體屬性和值钥勋。這方面的代表有g(shù)oogle protobuf炬转,thrift也屬于此類。

3. 無解析型

? ? ? ?傳說中百度的infpack實(shí)現(xiàn)算灸,就是借助該種方式來實(shí)現(xiàn)扼劈,丟棄了很多有效信息,性能/壓縮比最好菲驴,不過向后兼容需要開發(fā)做一定的工作荐吵,詳情不知。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赊瞬,一起剝皮案震驚了整個(gè)濱河市先煎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌巧涧,老刑警劉巖薯蝎,帶你破解...
    沈念sama閱讀 221,331評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異谤绳,居然都是意外死亡占锯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評論 3 398
  • 文/潘曉璐 我一進(jìn)店門缩筛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烟央,“玉大人,你說我怎么就攤上這事歪脏。” “怎么了粮呢?”我有些...
    開封第一講書人閱讀 167,755評論 0 360
  • 文/不壞的土叔 我叫張陵婿失,是天一觀的道長。 經(jīng)常有香客問我啄寡,道長豪硅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,528評論 1 296
  • 正文 為了忘掉前任挺物,我火速辦了婚禮懒浮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘识藤。我一直安慰自己砚著,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,526評論 6 397
  • 文/花漫 我一把揭開白布痴昧。 她就那樣靜靜地躺著稽穆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪赶撰。 梳的紋絲不亂的頭發(fā)上舌镶,一...
    開封第一講書人閱讀 52,166評論 1 308
  • 那天柱彻,我揣著相機(jī)與錄音,去河邊找鬼餐胀。 笑死哟楷,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的否灾。 我是一名探鬼主播卖擅,決...
    沈念sama閱讀 40,768評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼坟冲!你這毒婦竟也來了磨镶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,664評論 0 276
  • 序言:老撾萬榮一對情侶失蹤健提,失蹤者是張志新(化名)和其女友劉穎琳猫,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體私痹,經(jīng)...
    沈念sama閱讀 46,205評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡脐嫂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,290評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了紊遵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片账千。...
    茶點(diǎn)故事閱讀 40,435評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖暗膜,靈堂內(nèi)的尸體忽然破棺而出匀奏,到底是詐尸還是另有隱情,我是刑警寧澤学搜,帶...
    沈念sama閱讀 36,126評論 5 349
  • 正文 年R本政府宣布娃善,位于F島的核電站,受9級(jí)特大地震影響瑞佩,放射性物質(zhì)發(fā)生泄漏聚磺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,804評論 3 333
  • 文/蒙蒙 一炬丸、第九天 我趴在偏房一處隱蔽的房頂上張望瘫寝。 院中可真熱鬧,春花似錦稠炬、人聲如沸焕阿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捣鲸。三九已至,卻和暖如春闽坡,著一層夾襖步出監(jiān)牢的瞬間栽惶,已是汗流浹背愁溜。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留外厂,地道東北人冕象。 一個(gè)月前我還...
    沈念sama閱讀 48,818評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像汁蝶,于是被迫代替她去往敵國和親渐扮。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,442評論 2 359