Apache Thrift - 可伸縮的跨語言服務(wù)開發(fā)框架

Apache Thrift - 可伸縮的跨語言服務(wù)開發(fā)框架

RPC技術(shù)及實(shí)現(xiàn)簡介

RPC框架原理圖.png

首先思考一下分布式系統(tǒng)中的 RPC (Remote Procedure Call) 問題,一個(gè)完整的 RPC 模塊需要可以分為三個(gè)層次

  • 服務(wù)層(service):RPC 接口定義與實(shí)現(xiàn)
  • 協(xié)議層(protocol):RPC 報(bào)文格式和數(shù)據(jù)編碼格式
  • 傳輸層(transport):實(shí)現(xiàn)底層的通信(如 socket)以及系統(tǒng)相關(guān)的功能(如事件循環(huán)、多線程)
    在實(shí)際的大型分布式系統(tǒng)中,不同的服務(wù)往往會(huì)使用不同的語言來實(shí)現(xiàn),所以一般的 RPC 系統(tǒng)會(huì)提供一種跨語言的過程調(diào)用功能,比如一段用C++實(shí)現(xiàn)的客戶端代碼可以遠(yuǎn)程調(diào)用一個(gè)用 Java 實(shí)現(xiàn)的服務(wù)。實(shí)現(xiàn)跨語言 RPC 有兩種方法:
  • 靜態(tài)代碼生成:開發(fā)者用一種中間語言(IDL,接口定義語言)來定義 RPC 的接口和數(shù)據(jù)類型,然后通過一個(gè)編譯器來生成不同語言的代碼(如C++, Java, Python),并由生成的代碼來負(fù)責(zé) RPC 協(xié)議層和傳輸層的實(shí)現(xiàn)。例如,服務(wù)的實(shí)現(xiàn)用C++,則服務(wù)端需要生成實(shí)現(xiàn)RPC協(xié)議和傳輸層的C++代碼,服務(wù)層使用生成的代碼來實(shí)現(xiàn)與客戶端的通信;而如果客戶端用 Python,則客戶端需要生成Python代碼。
  • 基于“自省”的動(dòng)態(tài)類型系統(tǒng)來實(shí)現(xiàn):協(xié)議和傳輸層可以只用一種語言實(shí)現(xiàn)成一個(gè)庫,但是這種語言需要關(guān)聯(lián)一個(gè)具備“自省”或者反射機(jī)制的動(dòng)態(tài)類型系統(tǒng),對外提供其他語言的綁定,客戶端和服務(wù)端通過語言綁定來使用 RPC。比如,可以考慮用 C 和 GObject 實(shí)現(xiàn)一個(gè) RPC 庫,然后通過 GObject 實(shí)現(xiàn)其他語言的綁定。

第一種方法的優(yōu)點(diǎn)是RPC的協(xié)議層和傳輸層的實(shí)現(xiàn)不需要和某種動(dòng)態(tài)類型系統(tǒng)(如GObject)綁定在一起,同時(shí)避免了動(dòng)態(tài)類型檢查和轉(zhuǎn)換,程序效率比較高,但是它的缺點(diǎn)是要為不同語言提供不同的 RPC 協(xié)議層和傳輸層實(shí)現(xiàn)。第二種方法的主要難度在于語言綁定和通用的對象串行化機(jī)制的實(shí)現(xiàn),同時(shí)也需要考慮效率的問題。
Thrift 是一個(gè)基于靜態(tài)代碼生成的跨語言的RPC協(xié)議棧實(shí)現(xiàn),它可以生成包括C++, Java, Python, Ruby, PHP 等主流語言的代碼,這些代碼實(shí)現(xiàn)了 RPC 的協(xié)議層和傳輸層功能,從而讓用戶可以集中精力于服務(wù)的調(diào)用和實(shí)現(xiàn)。Cassandra 的服務(wù)訪問協(xié)議是基于 Thrift 來實(shí)現(xiàn)的

Thrift介紹

111947340627376.png

Thrift源于大名鼎鼎的facebook之手,在2007年facebook提交Apache基金會(huì)將Thrift作為一個(gè)開源項(xiàng)目,對于當(dāng)時(shí)的facebook來說創(chuàng)造thrift是為了解決facebook系統(tǒng)中各系統(tǒng)間大數(shù)據(jù)量的傳輸通信以及系統(tǒng)之間語言環(huán)境不同需要跨平臺(tái)的特性。所以thrift可以支持多種程序語言,例如: C++, C#, Cocoa, Erlang, Haskell, Java, Ocami, Perl, PHP, Python, Ruby, Smalltalk. 在多種不同的語言之間通信thrift可以作為二進(jìn)制的高性能的通訊中間件,支持?jǐn)?shù)據(jù)(對象)序列化和多種類型的RPC服務(wù)。Thrift適用于程序?qū)Τ?序靜態(tài)的數(shù)據(jù)交換,需要先確定好他的數(shù)據(jù)結(jié)構(gòu),他是完全靜態(tài)化的,當(dāng)數(shù)據(jù)結(jié)構(gòu)發(fā)生變化時(shí),必須重新編輯IDL文件,代碼生成,再編譯載入的流程,跟其他IDL工具相比較可以視為是Thrift的弱項(xiàng),Thrift適用于搭建大型數(shù)據(jù)交換及存儲(chǔ)的通用工具,對于大型系統(tǒng)中的內(nèi)部數(shù)據(jù)傳輸相對于JSON和xml無論在性能、傳輸大小上有明顯的優(yōu)勢。

Thrift 主要由5個(gè)部分組成:

  • 類型系統(tǒng)以及 IDL 編譯器:負(fù)責(zé)由用戶給定的 IDL 文件生成相應(yīng)語言的接口代碼
  • TProtocol:實(shí)現(xiàn) RPC 的協(xié)議層,可以選擇多種不同的對象串行化方式,如 JSON, Binary。
  • TTransport:實(shí)現(xiàn) RPC 的傳輸層,同樣可以選擇不同的傳輸層實(shí)現(xiàn),如socket, 非阻塞的 socket, MemoryBuffer 等。
  • TProcessor:作為協(xié)議層和用戶提供的服務(wù)實(shí)現(xiàn)之間的紐帶,負(fù)責(zé)調(diào)用服務(wù)實(shí)現(xiàn)的接口。
  • TServer:聚合 TProtocol, TTransport 和 TProcessor 幾個(gè)對象。

上述的這5個(gè)部件都是在 Thrift 的源代碼中通過為不同語言提供庫來實(shí)現(xiàn)的,這些庫的代碼在 Thrift 源碼目錄的 lib 目錄下面,在使用 Thrift 之前需要先熟悉與自己的語言對應(yīng)的庫提供的接口。

Thrift 包含一個(gè)完整的堆棧結(jié)構(gòu)用于構(gòu)建客戶端和服務(wù)器端。下圖描繪了 Thrift 的整體架構(gòu)。

674508-20160314134028537-1307650758.jpg

數(shù)據(jù)類型
Thrift 腳本可定義的數(shù)據(jù)類型包括以下幾種類型:

  • 基本類型
    bool:布爾值,true 或 false,對應(yīng) C#的 bool
    byte:8 位有符號(hào)整數(shù),對應(yīng) C#的 byte
    i16:16 位有符號(hào)整數(shù),對應(yīng) C#的 short
    i32:32 位有符號(hào)整數(shù),對應(yīng) C#的 int
    i64:64 位有符號(hào)整數(shù),對應(yīng) C#的 long
    double:64 位浮點(diǎn)數(shù),對應(yīng) C#的 double
    string:未知編碼文本或二進(jìn)制字符串,對應(yīng) C#的 string

  • 結(jié)構(gòu)體類型
    struct:定義公共的對象,類似于 C 語言中的結(jié)構(gòu)體定義,在 C#中是一個(gè)實(shí)體類

  • 容器類型
    list:對應(yīng) C#的 List<T> 有序集合
    set:對應(yīng) C#的 HashSet<T>無序但是不能重復(fù)的集合
    map:對應(yīng) C#的 Dictionary<TKey,TValue>鍵值對集合,鍵不能重復(fù)

  • 異常類型
    exception:對應(yīng) C#的 Exception

  • 服務(wù)類型
    service:對應(yīng)服務(wù)的類

Thrift的協(xié)議棧結(jié)構(gòu)

Thrift的協(xié)議棧結(jié)構(gòu).png

Thrift是一種c/s的架構(gòu)體系.在最上層是用戶自行實(shí)現(xiàn)的業(yè)務(wù)邏輯代碼.第二層是由thrift編譯器自動(dòng)生成的代碼,主要用于結(jié)構(gòu)化數(shù)據(jù)的解析,發(fā)送和接收。TServer主要任務(wù)是高效的接受客戶端請求,并將請求轉(zhuǎn)發(fā)給Processor處理。Processor負(fù)責(zé)對客戶端的請求做出響應(yīng),包括RPC請求轉(zhuǎn)發(fā),調(diào)用參數(shù)解析和用戶邏輯調(diào)用,返回值寫回等處理。從TProtocol以下部分是thirft的傳輸協(xié)議和底層I/O通信。TProtocol是用于數(shù)據(jù)類型解析的,將結(jié)構(gòu)化數(shù)據(jù)轉(zhuǎn)化為字節(jié)流給TTransport進(jìn)行傳輸。TTransport是與底層數(shù)據(jù)傳輸密切相關(guān)的傳輸層,負(fù)責(zé)以字節(jié)流方式接收和發(fā)送消息體,不關(guān)注是什么數(shù)據(jù)類型。底層IO負(fù)責(zé)實(shí)際的數(shù)據(jù)傳輸,包括socket、文件和壓縮數(shù)據(jù)流等。

Thrift支持的傳輸協(xié)議

Thrift支持多種傳輸協(xié)議,我們可以根據(jù)自己的需要來選擇合適的類型,總體上來說,分為文本傳輸和二進(jìn)制傳輸,由于二進(jìn)制傳輸在傳輸速率和節(jié)省帶寬上有優(yōu)勢,所以大部分情況下使用二進(jìn)制傳輸是比較好的選擇.

  • TBinaryProtocol:使用二進(jìn)制編碼格式傳輸,是thrift的默認(rèn)傳輸協(xié)議
  • TCompactProtocol:使用壓縮格式傳輸
  • TJSONProtocol :使用JSON格式傳輸
  • TDebugProtocol – 使用易懂可讀的文本格式進(jìn)行傳輸,以便于debug
  • TSimpleJSONProtocol – 提供JSON只寫的協(xié)議,適用于通過腳本語言解析

Thrift支持的服務(wù)模型

  • TSimpleServer:
    這種工作模式只有一個(gè)線程,循環(huán)監(jiān)聽傳過來的請求并對其進(jìn)行處理,處理完才能接受下一個(gè)請求,是一種阻塞式IO的實(shí)現(xiàn),因?yàn)樾时容^低,實(shí)際線上環(huán)境一般用不到.一般用于開發(fā)時(shí)候演示工作流程時(shí)使用.

  • TNonblockingServer:
    這種模式與TsimpleServer最大的區(qū)別就是使用NIO,也就是非阻塞是IO的方式實(shí)現(xiàn)IO的多路復(fù)用,它可以同時(shí)監(jiān)聽多個(gè)socket的變化,但因?yàn)闃I(yè)務(wù)處理上還是單線程模式,所以在一些業(yè)務(wù)處理比較復(fù)雜耗時(shí)的時(shí)候效率還是不高,因?yàn)槎鄠€(gè)請求任務(wù)依然需要排隊(duì)一個(gè)一個(gè)進(jìn)行處理.

  • TThreadPoolServer:
    這種模式引入了線程池,主線程只負(fù)責(zé)accept,即監(jiān)聽Socket,當(dāng)有新的請求(客戶端Socket)來時(shí),就會(huì)在線程池里起一個(gè)線程來處理業(yè)務(wù)邏輯,這樣在并發(fā)量比較大的時(shí)候(但不超過線程池的數(shù)量)每個(gè)請求都能及時(shí)被處理,效率比較高,但一旦并發(fā)量很大的時(shí)候(超過線程池?cái)?shù)量),后面來的請求也只能排隊(duì)等待.

  • TThreadedSelectorServer:
    這是一種多線程半同步半異步的服務(wù)模型,是Thrift提供的最復(fù)雜最高級的服務(wù)模型,內(nèi)部有一個(gè)專門負(fù)責(zé)處理監(jiān)聽Socket的線程,有多個(gè)專門處理業(yè)務(wù)中網(wǎng)絡(luò)IO的線程,有一個(gè)專門負(fù)責(zé)決定將新Socket連接分配給哪一個(gè)線程處理的起負(fù)載均衡作用的線程,還有一個(gè)工作線程池.這種模型既可以響應(yīng)大量并發(fā)連接的請求又可以快速對wangluoIO進(jìn)行讀寫,能適配很多場景,因此是一種使用比較高頻的服務(wù)模型.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,976評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,958評論 2 373

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