Apache Thrift 安裝及快速入門

Apache Thrift是什么?

The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages.

Apache Thrift軟件框架用于可擴(kuò)展的跨語(yǔ)言服務(wù)開(kāi)發(fā)遵班,將軟件堆棧與代碼生成引擎相結(jié)合擒抛,構(gòu)建可在C ++,Java,Python,PHP,Ruby疾掰,Erlang,Perl徐紧,Haskell静檬,C#之間高效無(wú)縫工作的服務(wù), Cocoa并级,JavaScript拂檩,Node.js,Smalltalk嘲碧,OCaml和Delphi等語(yǔ)言稻励。

Thrift最初由facebook研發(fā),主要用于各個(gè)服務(wù)之間的RPC通信,支持跨語(yǔ)言望抽,支持的語(yǔ)言有C++加矛,Java,Python煤篙,PHP斟览,Ruby,Erlang辑奈,PErl苛茂,Haskell,C#鸠窗,Cocoa味悄,JavaScript,Node.js,
Smalltalk,and OCaml都支持塌鸯。

Thrift是一個(gè)典型的CS(客戶端/服務(wù)端)結(jié)構(gòu),客戶端和服務(wù)端可以使用不同的語(yǔ)言開(kāi)發(fā)唐片。既然客戶端和服務(wù)器端能使用不同的語(yǔ)言開(kāi)發(fā)丙猬,那么一定就要有一種中間語(yǔ)言來(lái)關(guān)聯(lián)客戶端和服務(wù)器端的語(yǔ)言。這種語(yǔ)言就是IDL(Interface Description Language)费韭。

Thrift不支持無(wú)符號(hào)類型茧球,因?yàn)楹芏嗑幊陶Z(yǔ)言不存在無(wú)符號(hào)類型,比如說(shuō)java星持。一個(gè)RPC框架如果支持多種語(yǔ)言抢埋,那么這個(gè)RPC框架所支持的數(shù)據(jù)類型一定是這個(gè)RPC框架多語(yǔ)言支持的數(shù)據(jù)類型的交集。

Apache Thrift的一些概念

Thrift支持的數(shù)據(jù)類型

bool: 布爾類型(true或者false)
byte: 有符號(hào)字節(jié)
i16: 16位有符號(hào)整數(shù)
i32: 32位有符號(hào)整數(shù)
i64: 64位有符號(hào)整數(shù)
double: 64位浮點(diǎn)數(shù)
string: 字符串

集合中的元素可以是除了service之外的任何類型督暂,包括exception揪垄。這邊的service和exception是Thrift支持的組件,Thrift支持三種組件逻翁,分別是Structs(結(jié)構(gòu)體)饥努,Service(客戶端和服務(wù)端通信的接口),exception(客戶端和服務(wù)端通信接口拋出的異常)

結(jié)構(gòu)體(struct)
就像C語(yǔ)言一樣八回,Thrift支持struct類型酷愧,目的就是將一些數(shù)據(jù)聚合在一起,方便傳輸管理缠诅,struct的定義形式如下:

struct People{
    1:string name;
    2:i32 age;
    3:string gender;
 }

枚舉(enum)
枚舉的定義形式和Java的Enum定義類似

enum Gender{
    MALE,
    FEMALE
}

異常(exception)
Thrift支持自定義exception溶浴,規(guī)則與struct一樣

exception RequestException{
    1: i32 code;
    2: string reason;
 }

服務(wù)(service)
Thrift定義服務(wù)相當(dāng)于Java中創(chuàng)建Interface一樣,創(chuàng)建的service經(jīng)過(guò)代碼生成命令之后就會(huì)生成客戶端和服務(wù)器端的框架代碼管引。定義形式如下:

service HelloWorldService{
    //service中定義的函數(shù)士败,相當(dāng)于Java Interface中定義的方法
    string doAction(1:string name,2:i32 age);
}

類型定義
Thrift支持類似C++一樣的typedef定義,比如我們對(duì)i32不熟悉汉匙,我們就使用int類代替i32拱烁,比如我們對(duì)i64不熟悉生蚁,我們就使用long代替i64

typedef i32 int 
typedef i64 long

常量(const)
Thrift也支持常量定義,使用const關(guān)鍵字

const i32 MIN_GATE=30
const string MY_WEBSITE="http://facebook.com"

命名空間
Thrift的命名空間相當(dāng)于java中的package的意思戏自,主要目的是組織代碼邦投。Thift使用關(guān)鍵字namespave定義命名空間:

namespace java com.test.thift.demo

格式是:namespace 語(yǔ)言名 路徑

文件包含
Thrift也支持文件包含,相當(dāng)于C/C++中的include擅笔,java中的import志衣。使用關(guān)鍵字include定義:

include "global.thift"

注釋
Thrift注釋方式支持shell風(fēng)格的注釋,支持C/C++風(fēng)格的注釋猛们,即#和開(kāi)頭的語(yǔ)句都當(dāng)作注釋念脯,/**/包裹的語(yǔ)句也是注釋。

可選與必選
Thrift提供兩個(gè)關(guān)鍵字required弯淘,optional绿店,分別用于表示對(duì)應(yīng)的字段是必填的還是可選的

struct People{
    1:required string name;
    2:optional i32 age;
}

Thrift傳輸格式(協(xié)議)

  1. TBinaryProtocal-二進(jìn)制格式
  2. TCompactProtocol-壓縮格式
  3. TJSONProtocol-JSON格式
  4. TSimpleJSONProtocol-提供JSON只寫(xiě)協(xié)議,生成的文件很容易通過(guò)腳本語(yǔ)言解析
  5. TDebugProtocol-使用易懂的可讀文本格式庐橙,以便于debug

Thrift數(shù)據(jù)傳輸方式

  1. TSocket-阻塞式socket
  2. TFramedTransport-以frame為單位進(jìn)行傳輸假勿,非阻塞式服務(wù)中使用
  3. TFileTransport-以文件形式進(jìn)行傳輸
  4. TMemoryInputTransport-將內(nèi)存用語(yǔ)I/O,Java實(shí)現(xiàn)時(shí)內(nèi)部實(shí)際使用了簡(jiǎn)單的ByteArrayOutputStream态鳖。
  5. TZlibTransport-使用zlib進(jìn)行壓縮转培,與其他傳輸方式聯(lián)合使用。當(dāng)前無(wú)java實(shí)現(xiàn)浆竭。

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

  1. TThreadPoolServer - 簡(jiǎn)單的單線程服務(wù)模型浸须,常用于測(cè)試
  2. TSimpleServer - 多線程服務(wù)模型,使用標(biāo)準(zhǔn)的阻塞式IO
  3. TNonblockingServer - 多線程服務(wù)模型邦泄,使用非阻塞式IO(需要使用TFramedTransport數(shù)據(jù)傳輸方式)
  4. THsHaServer-THsHa引入了線程池去處理删窒,其模型把讀寫(xiě)任務(wù)放到線程池處理;Half-sync/Half-async的處理模式,Half-async是在處理IO事件上
    (accept/read/write io),Half-sync用于handler對(duì)rpc的同步處理虎韵。

注意
一般在工作中使用TCompactProtocol傳輸協(xié)議易稠,使用TFramedTransport數(shù)據(jù)傳輸方式,使用THsHaServer服務(wù)模型包蓝。

Thrift支持的容器類型

list:一系列由T類型的數(shù)據(jù)組成的有序列表驶社,元素可以重復(fù)。
set:一系列由T類型的數(shù)據(jù)組成的無(wú)序集合测萎,元素不可重復(fù)亡电。
map:一個(gè)字典結(jié)構(gòu),key為k類型硅瞧,value為V類型份乒,相當(dāng)于java中的HashMap
以上集合容器都可以使用泛型的。

Thrift工作原理

如何實(shí)現(xiàn)多語(yǔ)言之間的通信?
數(shù)據(jù)傳輸實(shí)現(xiàn)socket(多種語(yǔ)言均支持)或辖,數(shù)據(jù)再以特定的格式(String等)發(fā)送瘾英,接收方語(yǔ)言進(jìn)行解析。
Apache Thrift定義的thrift的文件(IDL)颂暇,由thrift文件(IDL)生成雙方語(yǔ)言的接口缺谴,model,在生成的model以及接口中會(huì)有解碼編碼的代碼耳鸯。

Thrift 架構(gòu)

Thrift架構(gòu)圖

Thrift的安裝

官方網(wǎng)站提供的下載安裝地址湿蛔,根據(jù)不同的操作系統(tǒng)選擇自己的安裝方式

mac電腦推薦使用更簡(jiǎn)單的安裝方式Homebrew工具,
Homebrew官方網(wǎng)址

先安裝Homebrew:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

安裝成功之后县爬,檢測(cè)Homebrew:

?  ~ which brew
/usr/local/bin/brew

安裝Apache Thrift

?  ~ brew install thrift

安裝完成之后:
查看具體安裝信息:

?  ~ which thrift
/usr/local/bin/thrift
?  ~ thrift --version
Thrift version 0.10.0
thrift --help

快速入門

定義idl文件

先定義一個(gè)idl文件(接口描述文件)阳啥,定義了結(jié)構(gòu)體(struct),異常(exception)和服務(wù)(service)

namespace java thrift.generated

typedef i16 short
typedef i32 int
typedef i64 long
typedef bool boolean
typedef string String

struct Person{
    1: optional String username,
    2: optional int age,
    3: optional boolean married
}

exception DataException{
    1: optional String message,
    2: optional String callStack,
    3: optional String date
}

service PersonService{
    Person getPersonByUsername(1: required String username) throws (1: DataException dateException),

    void savePerson(1: required Person person) throws (1: DataException dataException)
}

使用thrift編譯器生成編譯文件

thrift --gen java src/thrift/data.thrift
java生成的代碼

將生成的代碼復(fù)制到src/main目錄下财喳,發(fā)現(xiàn)報(bào)錯(cuò)察迟,加入java的依賴pom文件:

<dependency>
    <groupId>org.apache.thrift</groupId>
    <artifactId>libthrift</artifactId>
    <version>0.10.0</version>
</dependency>

使用java編寫(xiě)客戶端與服務(wù)器端的代碼

編寫(xiě)接口實(shí)現(xiàn)類,實(shí)際開(kāi)發(fā)中放在服務(wù)端

import org.apache.thrift.TException;
import thrift.generated.DataException;
import thrift.generated.Person;
import thrift.generated.PersonService;

public class PersonServiceImpl implements PersonService.Iface{

    @Override
    public Person getPersonByUsername(String username) throws DataException, TException {
        System.out.println("Got client Param:" + username);

        Person person = new Person();
        person.setUsername(username);
        person.setAge(32);
        person.setMarried(true);

        return person;
    }

    @Override
    public void savePerson(Person person) throws DataException, TException {
        System.out.println("Got Client Param: ");

        System.out.println(person.getUsername());
        System.out.println(person.getAge());
        System.out.println(person.isMarried());
    }
}

服務(wù)器端代碼:

import org.apache.thrift.TProcessorFactory;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.TServer;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TNonblockingServerSocket;
import thrift.generated.PersonService;

public class ThriftServer {
    public static void main(String[] args) throws Exception{

        TNonblockingServerSocket socket = new TNonblockingServerSocket(8899);
        THsHaServer.Args arg = new THsHaServer.Args(socket).minWorkerThreads(2).maxWorkerThreads(4);
        //范型就是實(shí)現(xiàn)的接收類
        PersonService.Processor<PersonServiceImpl> processor = new PersonService.Processor<>(new PersonServiceImpl());

        //表示協(xié)議層次(壓縮協(xié)議)
        arg.protocolFactory(new TCompactProtocol.Factory());
        //表示傳輸層次
        arg.transportFactory(new TFramedTransport.Factory());
        arg.processorFactory(new TProcessorFactory(processor));

        //半同步半異步的server
        TServer server = new THsHaServer(arg);

        System.out.println("Thrift Server started!");

        //死循環(huán)耳高,永遠(yuǎn)不會(huì)退出
        server.serve();
    }
}

客戶端代碼:

import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFastFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import thrift.generated.Person;
import thrift.generated.PersonService;

//服務(wù)端的協(xié)議和客戶端的協(xié)議要一致
public class ThriftClient {
    public static void main(String[] args) {

        TTransport tTransport = new TFastFramedTransport(new TSocket("localhost",8899),600);
        TProtocol tProtocol = new TCompactProtocol(tTransport);
        PersonService.Client client = new PersonService.Client(tProtocol);

        try{
            tTransport.open();

            Person person = client.getPersonByUsername("張三");

            System.out.println(person.getUsername());
            System.out.println(person.getAge());
            System.out.println(person.isMarried());

            System.out.println("............");

            Person person2 = new Person();

            person2.setUsername("李四");
            person2.setAge(30);
            person2.setMarried(true);

            client.savePerson(person2);
        }catch (Exception ex){
            throw new  RuntimeException(ex.getMessage(),ex);
        }finally {
            tTransport.close();
        }
    }
}

啟動(dòng)服務(wù)器卷拘,再啟動(dòng)客戶端,
客戶端打幼8摺:

Received 1
張三
32
true
............
Received 2

服務(wù)器端打印:

Thrift Server started!
Got client Param:張三
Got Client Param: 
李四
30
true

跟我們之前的Google Protobuf相比污筷,Google Protobuf只是進(jìn)行編解碼(序列化與反序列)操作工闺,使用netty作為網(wǎng)絡(luò)載體,進(jìn)行遠(yuǎn)程方法調(diào)用瓣蛀。而Thrift不僅僅既可以進(jìn)行編解碼工作陆蟆,還提供傳輸對(duì)象功能,并且可以自己定義業(yè)務(wù)接口惋增。

參考資料

官網(wǎng)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末叠殷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子诈皿,更是在濱河造成了極大的恐慌林束,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稽亏,死亡現(xiàn)場(chǎng)離奇詭異壶冒,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)截歉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門胖腾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事咸作∠前ⅲ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵记罚,是天一觀的道長(zhǎng)墅诡。 經(jīng)常有香客問(wèn)我,道長(zhǎng)毫胜,這世上最難降的妖魔是什么书斜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮酵使,結(jié)果婚禮上荐吉,老公的妹妹穿的比我還像新娘。我一直安慰自己口渔,他們只是感情好样屠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著缺脉,像睡著了一般痪欲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上攻礼,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天业踢,我揣著相機(jī)與錄音,去河邊找鬼礁扮。 笑死知举,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的太伊。 我是一名探鬼主播雇锡,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼僚焦!你這毒婦竟也來(lái)了锰提?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤芳悲,失蹤者是張志新(化名)和其女友劉穎立肘,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體名扛,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赛不,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了罢洲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片踢故。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡文黎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出殿较,到底是詐尸還是另有隱情耸峭,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布淋纲,位于F島的核電站劳闹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏洽瞬。R本人自食惡果不足惜本涕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伙窃。 院中可真熱鬧菩颖,春花似錦、人聲如沸为障。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鳍怨。三九已至呻右,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鞋喇,已是汗流浹背声滥。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留侦香,地道東北人醒串。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鄙皇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仰挣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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

  • 轉(zhuǎn)自:http://blog.csdn.net/kesonyk/article/details/50924489 ...
    晴天哥_王志閱讀 24,808評(píng)論 2 38
  • 前言: 目前流行的服務(wù)調(diào)用方式有很多種伴逸,例如基于 SOAP 消息格式的 Web Service,基于 JSON 消...
    我是嘻哈大哥閱讀 1,559評(píng)論 0 9
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理膘壶,服務(wù)發(fā)現(xiàn)错蝴,斷路器,智...
    卡卡羅2017閱讀 134,654評(píng)論 18 139
  • Thrift是什么颓芭? Thrift是Facebook于2007年開(kāi)發(fā)的跨語(yǔ)言的rpc服框架顷锰,提供多語(yǔ)言的編譯功能,...
    jiangmo閱讀 9,415評(píng)論 0 6
  • 與老公同齡亡问,所以因?yàn)槭峭粚傧嗟脑蚬僮希芏嗥鈧€(gè)性都很像肛宋。我們常常吵架,吵的時(shí)候感覺(jué)天崩地裂束世,眼淚嘩嘩嘩的流酝陈,那時(shí)...
    古裝我不裝閱讀 194評(píng)論 0 0