thrift入門教程

概述

本文是入門教程祖很,想要了解thrift的源碼實(shí)現(xiàn)可以移步我的CSDN專欄thrift源碼解析

Thrift最初由Facebook研發(fā)名斟,主要用于各個服務(wù)之間的RPC通信恤磷,支持跨語言危号,常用的語言比如C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml都支持。Thrift是一個典型的CS(客戶端/服務(wù)端)結(jié)構(gòu)舆吮,客戶端和服務(wù)端可以使用不同的語言開發(fā)。既然客戶端和服務(wù)端能使用不同的語言開發(fā)队贱,那么一定就要有一種中間語言來關(guān)聯(lián)客戶端和服務(wù)端的語言色冀,沒錯,這種語言就是IDL(Interface Description Language)柱嫌。

Thrift IDL

本節(jié)介紹Thrift的接口定義語言锋恬,Thrift IDL支持的數(shù)據(jù)類型包含:

基本類型

thrift不支持無符號類型,因?yàn)楹芏嗑幊陶Z言不存在無符號類型编丘,比如java

  • byte: 有符號字節(jié)
  • i16: 16位有符號整數(shù)
  • i32: 32位有符號整數(shù)
  • i64: 64位有符號整數(shù)
  • double: 64位浮點(diǎn)數(shù)
  • string: 字符串

容器類型

集合中的元素可以是除了service之外的任何類型伶氢,包括exception。

  • list<T>: 一系列由T類型的數(shù)據(jù)組成的有序列表瘪吏,元素可以重復(fù)
  • set<T>: 一系列由T類型的數(shù)據(jù)組成的無序集合癣防,元素不可重復(fù)
  • map<K, V>: 一個字典結(jié)構(gòu),key為K類型掌眠,value為V類型蕾盯,相當(dāng)于Java中的HMap<K,V>

結(jié)構(gòu)體(struct)

就像C語言一樣,thrift也支持struct類型蓝丙,目的就是將一些數(shù)據(jù)聚合在一起级遭,方便傳輸管理。struct的定 義形式如下:

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

枚舉(enum)

枚舉的定義形式和Java的Enum定義差不多渺尘,例如:

enum Sex {
    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)過代碼生成命令之后就會生成客戶端和服務(wù)端的框架代碼丢郊。定義形式如下:

service HelloWordService {
     // service中定義的函數(shù)盔沫,相當(dāng)于Java interface中定義的函數(shù)
     string doAction(1: string name, 2: i32 age);
 }

類型定義

thrift支持類似C++一樣的typedef定義,比如:

typedef i32 Integer
typedef i64 Long

注意枫匾,末尾沒有逗號或者分號

常量(const)

thrift也支持常量定義架诞,使用const關(guān)鍵字,例如:

const i32 MAX_RETRIES_TIME = 10
const string MY_WEBSITE = "http://qifuguang.me";

末尾的分號是可選的干茉,可有可無谴忧,并且支持16進(jìn)制賦值

命名空間

thrift的命名空間相當(dāng)于Java中的package的意思,主要目的是組織代碼角虫。thrift使用關(guān)鍵字namespace定義命名空間沾谓,例如:

namespace java com.winwill.thrift

格式是:namespace 語言名 路徑, 注意末尾不能有分號戳鹅。

文件包含

thrift也支持文件包含均驶,相當(dāng)于C/C++中的include,Java中的import粉楚。使用關(guān)鍵字include定義辣恋,例 如:

include "global.thrift"

注釋

thrift注釋方式支持shell風(fēng)格的注釋,支持C/C++風(fēng)格的注釋模软,即#和//開頭的語句都單當(dāng)做注釋伟骨,/**/包裹的語句也是注釋。

可選與必選

thrift提供兩個關(guān)鍵字required燃异,optional携狭,分別用于表示對應(yīng)的字段時必填的還是可選的。例如:

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

表示name是必填的回俐,age是可選的逛腿。

生成代碼

知道了怎么定義thirtf文件之后,我們需要用定義好的thrift文件生成我們需要的目標(biāo)語言的源碼仅颇,本文以生成java源碼為例单默。假設(shè)現(xiàn)在定義了如下一個thrift文件:

namespace java com.winwill.thrift

enum RequestType {
   SAY_HELLO,   //問好
   QUERY_TIME,  //詢問時間
}

struct Request {
   1: required RequestType type;  // 請求的類型,必選
   2: required string name;       // 發(fā)起請求的人的名字忘瓦,必選
   3: optional i32 age;           // 發(fā)起請求的人的年齡搁廓,可選
}

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

// 服務(wù)名
service HelloWordService {
   string doAction(1: Request request) throws (1:RequestException qe); // 可能拋出異常。
}

在終端運(yùn)行如下命令(前提是已經(jīng)安裝thrift):

thrift --gen java Test.thrift

則在當(dāng)前目錄會生成一個gen-java目錄耕皮,該目錄下會按照namespace定義的路徑名一次一層層生成文件夾境蜕,到gen-java/com/winwill/thrift/目錄下可以看到生成的4個Java類:


目錄結(jié)構(gòu)
目錄結(jié)構(gòu)

可以看到,thrift文件中定義的enum凌停,struct粱年,exception,service都相應(yīng)地生成了一個Java類罚拟,這就是能支持Java語言的基本的框架代碼台诗。

服務(wù)端實(shí)現(xiàn)

上面代碼生成這一步已經(jīng)將接口代碼生成了完箩,現(xiàn)在需要做的是實(shí)現(xiàn)HelloWordService的具體邏輯,實(shí)現(xiàn)的方式就是創(chuàng)建一個Java類拉庶,implements com.winwill.thrift.HelloWordService嗜憔,例如:

package com.winwill.thrift;


import org.apache.commons.lang3.StringUtils;
import org.apache.thrift.TException;

import java.util.Date;

/**
 * @author qifuguang
 * @date 15/9/11 15:53
 */
public class HelloWordServiceImpl implements com.winwill.thrift.HelloWordService.Iface {
    // 實(shí)現(xiàn)這個方法完成具體的邏輯秃励。
    public String doAction(com.winwill.thrift.Request request) throws com.winwill.thrift.RequestException, TException {
        System.out.println("Get request: " + request);
        if (StringUtils.isBlank(request.getName()) || request.getType() == null) {
            throw new com.winwill.thrift.RequestException();
        }
        String result = "Hello, " + request.getName();
        if (request.getType() == com.winwill.thrift.RequestType.SAY_HELLO) {
            result += ", Welcome!";
        } else {
            result += ", Now is " + new Date().toLocaleString();
        }
        return result;
    }
}

啟動服務(wù)

上面這個就是服務(wù)端的具體實(shí)現(xiàn)類氏仗,現(xiàn)在需要啟動這個服務(wù),所以需要一個啟動類夺鲜,啟動類的代碼如下:

package com.winwill.thrift;

import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;

import java.net.ServerSocket;

/**
 * @author qifuguang
 * @date 15/9/11 16:07
 */
public class HelloWordServer {
    public static void main(String[] args) throws Exception {
        ServerSocket socket = new ServerSocket(7912);
        TServerSocket serverTransport = new TServerSocket(socket);
        com.winwill.thrift.HelloWordService.Processor processor = new com.winwill.thrift.HelloWordService.Processor(new HelloWordServiceImpl());
        TServer server = new TSimpleServer(processor, serverTransport);
        System.out.println("Running server...");
        server.serve();
    }
}

運(yùn)行之后看到控制臺的輸出為:

Running server...

客戶端請求

現(xiàn)在服務(wù)已經(jīng)啟動皆尔,可以通過客戶端向服務(wù)端發(fā)送請求了,客戶端的代碼如下:

package com.winwill.thrift;

import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;

/**
 * @author qifuguang
 * @date 15/9/11 16:13
 */
public class HelloWordClient {
    public static void main(String[] args) throws Exception {
        TTransport transport = new TSocket("localhost", 8888);
        TProtocol protocol = new TBinaryProtocol(transport);

        // 創(chuàng)建client
        com.winwill.thrift.HelloWordService.Client client = new com.winwill.thrift.HelloWordService.Client(protocol);

        transport.open();  // 建立連接

        // 第一種請求類型
        com.winwill.thrift.Request request = new com.winwill.thrift.Request()
                .setType(com.winwill.thrift.RequestType.SAY_HELLO).setName("winwill2012").setAge(24);
        System.out.println(client.doAction(request));

        // 第二種請求類型
        request.setType(com.winwill.thrift.RequestType.QUERY_TIME).setName("winwill2012");
        System.out.println(client.doAction(request));

        transport.close();  // 請求結(jié)束币励,斷開連接
    }
}

運(yùn)行客戶端代碼慷蠕,得到結(jié)果:

Hello, winwill2012, Welcome!
Hello, winwill2012, Now is 2015-9-11 16:37:22

并且此時,服務(wù)端會有請求日志:

Running server...
Get request: Request(type:SAY_HELLO, name:winwill2012, age:24)
Get request: Request(type:QUERY_TIME, name:winwill2012, age:24)

可以看到食呻,客戶端成功將請求發(fā)到了服務(wù)端流炕,服務(wù)端成功地將請求結(jié)果返回給客戶端,整個通信過程完成仅胞。

注意事項(xiàng)

  • 本文為作者個人理解每辟,如理解有誤,請留言相告干旧,感激不盡渠欺;
  • 本文是入門教程,想要了解thrift的源碼實(shí)現(xiàn)可以移步我的CSDN專欄thrift源碼解析
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末椎眯,一起剝皮案震驚了整個濱河市挠将,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌编整,老刑警劉巖舔稀,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異掌测,居然都是意外死亡内贮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門赏半,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贺归,“玉大人,你說我怎么就攤上這事断箫》骱ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵仲义,是天一觀的道長婶熬。 經(jīng)常有香客問我剑勾,道長,這世上最難降的妖魔是什么赵颅? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任虽另,我火速辦了婚禮,結(jié)果婚禮上饺谬,老公的妹妹穿的比我還像新娘捂刺。我一直安慰自己,他們只是感情好募寨,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布族展。 她就那樣靜靜地躺著,像睡著了一般拔鹰。 火紅的嫁衣襯著肌膚如雪仪缸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天列肢,我揣著相機(jī)與錄音恰画,去河邊找鬼。 笑死瓷马,一個胖子當(dāng)著我的面吹牛拴还,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播决采,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼自沧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了树瞭?” 一聲冷哼從身側(cè)響起拇厢,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晒喷,沒想到半個月后孝偎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡凉敲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年衣盾,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爷抓。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡势决,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蓝撇,到底是詐尸還是另有隱情果复,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布渤昌,位于F島的核電站虽抄,受9級特大地震影響走搁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜迈窟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一私植、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧车酣,春花似錦曲稼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽者春。三九已至破衔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間钱烟,已是汗流浹背晰筛。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拴袭,地道東北人读第。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像拥刻,于是被迫代替她去往敵國和親怜瞒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

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