国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設(shè)計 > 正文

Thrift使用指南

2019-11-11 06:54:43
字體:
供稿:網(wǎng)友
轉(zhuǎn)載自:董的博客 http://dongxicheng.org/search-engine/thrift-guide/

1. 內(nèi)容概要

本文檔比較全面的介紹了thrift語法,代碼生成結(jié)構(gòu)和應(yīng)用經(jīng)驗。本文主要講述的對象是thrift文件,并未涉及其client和server的編寫方法。

2. 語法參考

2.1 Types

Thrift類型系統(tǒng)包括預定義基本類型,用戶自定義結(jié)構(gòu)體,容器類型,異常和服務(wù)定義

(1) 基本類型

12345678910111213

bool:布爾類型(trueor value),占一個字節(jié) byte:有符號字節(jié) i16:16位有符號整型 i32:32位有符號整型 i64:64位有符號整型 double:64位浮點數(shù) string:未知編碼或者二進制的字符串

注意,thrift不支持無符號整型,因為很多目標語言不存在無符號整型(如java)。

(2) 容器類型

Thrift容器與類型密切相關(guān),它與當前流行編程語言提供的容器類型相對應(yīng),采用java泛型風格表示的。Thrift提供了3種容器類型:

List<t1>:一系列t1類型的元素組成的有序表,元素可以重復

Set<t1>:一系列t1類型的元素組成的無序表,元素唯一

Map<t1,t2>:key/value對(key的類型是t1且key唯一,value類型是t2)。

容器中的元素類型可以是除了service以外的任何合法thrift類型(包括結(jié)構(gòu)體和異常)。

(3)  結(jié)構(gòu)體和異常

Thrift結(jié)構(gòu)體在概念上同C語言結(jié)構(gòu)體類型—— 一種將相關(guān)屬性聚集(封裝)在一起的方式。在面向?qū)ο笳Z言中,thrift結(jié)構(gòu)體被轉(zhuǎn)換成類。

異常在語法和功能上類似于結(jié)構(gòu)體,只不過異常使用關(guān)鍵字exception而不是struct關(guān)鍵字聲明。但它在語義上不同于結(jié)構(gòu)體——當定義一個RPC服務(wù)時,開發(fā)者可能需要聲明一個遠程方法拋出一個異常。

結(jié)構(gòu)體和異常的聲明將在下一節(jié)介紹。

(4)  服務(wù)

服務(wù)的定義方法在語法上等同于面向?qū)ο笳Z言中定義接口。Thrift編譯器會產(chǎn)生實現(xiàn)這些接口的client和server樁。具體參見下一節(jié)。

(5)  類型定義

Thrift支持C/C++風格的typedef:

123

typedefi32 MyInteger   //a typedefTweet ReTweet  //b

說明:

a.  末尾沒有逗號

b.   struct可以使用typedef

2.2   枚舉類型

可以像C/C++那樣定義枚舉類型,如:

123456789101112131415161718192021222324252627

enumTweetType { TWEET,      //a RETWEET = 2, //b DM = 0xa,  //c REPLY }       //d structTweet { 1: required i32 userId; 2: required string userName; 3: required string text; 4: optional Location loc; 5: optional TweetType tweetType = TweetType.TWEET // e 16: optional string language = "english" }

說明:

a.  編譯器默認從0開始賦值

b.  可以賦予某個常量某個整數(shù)

c.  允許常量是十六進制整數(shù)

d.  末尾沒有逗號

e.  給常量賦缺省值時,使用常量的全稱

注意,不同于PRotocol buffer,thrift不支持枚舉類嵌套,枚舉常量必須是32位的正整數(shù)

2.3   注釋

Thrfit支持shell注釋風格,C/C++語言中單行或者多行注釋風格

1234567891011

# This is a valid comment. /* * This is a multi-line comment. * Just like in C. */ // C++/Java style single-line comments work just as well.

2.4   命名空間

Thrift中的命名空間同C++中的namespace和java中的package類似,它們均提供了一種組織(隔離)代碼的方式。因為每種語言均有自己的命名空間定義方式(如python中有module),thrift允許開發(fā)者針對特定語言定義namespace:

123

namespacecpp com.example.project  // a namespacejava com.example.project // b

說明:

a.  轉(zhuǎn)化成namespace com { namespace example { namespace project {

b.  轉(zhuǎn)換成package com.example.project

2.5   文件包含

Thrift允許thrift文件包含,用戶需要使用thrift文件名作為前綴訪問被包含的對象,如:

123456789

include"tweet.thrift"          // a ... structTweetSearchResult { 1: list<tweet.Tweet> tweets; // b }

說明:

a.  thrift文件名要用雙引號包含,末尾沒有逗號或者分號

b.  注意tweet前綴

2.6   常量

Thrift允許用戶定義常量,復雜的類型和結(jié)構(gòu)體可使用JSON形式表示。

123

consti32 INT_CONST = 1234;    // a constmap<string,string> MAP_CONST = {"hello":"world","goodnight":"moon"}

說明:

a.  分號是可選的,可有可無;支持十六進制賦值。

2.7   定義結(jié)構(gòu)體

結(jié)構(gòu)體由一系列域組成,每個域有唯一整數(shù)標識符,類型,名字和可選的缺省參數(shù)組成。如:

123456789101112131415161718192021

structTweet { 1: required i32 userId;                  // a 2: required string userName;             // b 3: required string text; 4: optional Location loc;                // c 16: optional string language = "english"// d } structLocation {                            // e 1: required doublelatitude; 2: required doublelongitude; }

說明:

a.  每個域有一個唯一的,正整數(shù)標識符

b.  每個域可以標識為required或者optional(也可以不注明)

c.  結(jié)構(gòu)體可以包含其他結(jié)構(gòu)體

d.  域可以有缺省值

e.  一個thrift中可定義多個結(jié)構(gòu)體,并存在引用關(guān)系

規(guī)范的struct定義中的每個域均會使用required或者optional關(guān)鍵字進行標識。如果required標識的域沒有賦值,thrift將給予提示。如果optional標識的域沒有賦值,該域?qū)⒉粫恍蛄谢瘋鬏?。如果某個optional標識域有缺省值而用戶沒有重新賦值,則該域的值一直為缺省值。

與service不同,結(jié)構(gòu)體不支持繼承,即,一個結(jié)構(gòu)體不能繼承另一個結(jié)構(gòu)體。

2.8   定義服務(wù)

在流行的序列化/反序列化框架(如protocol buffer)中,thrift是少有的提供多語言間RPC服務(wù)的框架。

Thrift編譯器會根據(jù)選擇的目標語言為server產(chǎn)生服務(wù)接口代碼,為client產(chǎn)生樁代碼。

1234567891011121314151617181920

//“Twitter”與“{”之間需要有空格?。?!service Twitter { // 方法定義方式類似于C語言中的方式,它有一個返回值,一系列參數(shù)和可選的異常 // 列表. 注意,參數(shù)列表和異常列表定義方式與結(jié)構(gòu)體中域定義方式一致. voidping(),                                   // a boolpostTweet(1:Tweet tweet);                  // b TweetSearchResult searchTweets(1:string query); // c // ”oneway”標識符表示client發(fā)出請求后不必等待回復(非阻塞)直接進行下面的操作, // ”oneway”方法的返回值必須是void onewayvoidzip()                              // d }

說明:

a. 函數(shù)定義可以使用逗號或者分號標識結(jié)束

b. 參數(shù)可以是基本類型或者結(jié)構(gòu)體,參數(shù)是只讀的(const),不可以作為返回值!!!

c. 返回值可以是基本類型或者結(jié)構(gòu)體

d. 返回值可以是void

注意,函數(shù)中參數(shù)列表的定義方式與struct完全一樣

Service支持繼承,一個service可使用extends關(guān)鍵字繼承另一個service

3.  產(chǎn)生代碼

本節(jié)介紹thrift產(chǎn)生各種目標語言代碼的方式。本節(jié)從幾個基本概念開始,逐步引導開發(fā)者了解產(chǎn)生的代碼是怎么樣組織的,進而幫助開發(fā)者更快地明白thrift的使用方法。

概念

Thrift的網(wǎng)絡(luò)棧如下所示:

3.1   Transport

Transport層提供了一個簡單的網(wǎng)絡(luò)讀寫抽象層。這使得thrift底層的transport從系統(tǒng)其它部分(如:序列化/反序列化)解耦。以下是一些Transport接口提供的方法:

123456789

open close read write flush

除了以上幾個接口,Thrift使用ServerTransport接口接受或者創(chuàng)建原始transport對象。正如名字暗示的那樣,ServerTransport用在server端,為到來的連接創(chuàng)建Transport對象。

1234567

open listen accept close

3.2   Protocol

Protocol抽象層定義了一種將內(nèi)存中數(shù)據(jù)結(jié)構(gòu)映射成可傳輸格式的機制。換句話說,Protocol定義了datatype怎樣使用底層的Transport對自己進行編解碼。因此,Protocol的實現(xiàn)要給出編碼機制并負責對數(shù)據(jù)進行序列化。

Protocol接口的定義如下:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677

writeMessageBegin(name, type, seq) writeMessageEnd() writeStructBegin(name) writeStructEnd() writeFieldBegin(name, type, id) writeFieldEnd() writeFieldStop() writeMapBegin(ktype, vtype, size) writeMapEnd() writeListBegin(etype, size) writeListEnd() writeSetBegin(etype, size) writeSetEnd() writeBool(bool) writeByte(byte) writeI16(i16) writeI32(i32) writeI64(i64) writeDouble(double) writeString(string) name, type, seq = readMessageBegin() readMessageEnd() name = readStructBegin() readStructEnd() name, type, id = readFieldBegin() readFieldEnd() k, v, size = readMapBegin() readMapEnd() etype, size = readListBegin() readListEnd() etype, size = readSetBegin() readSetEnd() bool= readBool() byte = readByte() i16 = readI16() i32 = readI32() i64 = readI64() double= readDouble() string = readString()

下面是一些對大部分thrift支持的語言均可用的protocol:

(1)     binary:簡單的二進制編碼

(2)     Compact

(3)     Json

3.3   Processor

Processor封裝了從輸入數(shù)據(jù)流中讀數(shù)據(jù)和向數(shù)據(jù)數(shù)據(jù)流中寫數(shù)據(jù)的操作。讀寫數(shù)據(jù)流用Protocol對象表示。Processor的結(jié)構(gòu)體非常簡單:

12345

interface TProcessor { boolprocess(TProtocol in, TProtocol out) throws TException }

與服務(wù)相關(guān)的processor實現(xiàn)由編譯器產(chǎn)生。Processor主要工作流程如下:從連接中讀取數(shù)據(jù)(使用輸入protocol),將處理授權(quán)給handler(由用戶實現(xiàn)),最后將結(jié)果寫到連接上(使用輸出protocol)。

3.4   Server

Server將以上所有特性集成在一起:

(1)  創(chuàng)建一個transport對象

(2)  為transport對象創(chuàng)建輸入輸出protocol

(3)  基于輸入輸出protocol創(chuàng)建processor

(4)  等待連接請求并將之交給processor處理

3.5   應(yīng)用舉例

下面,我們討論thrift文件產(chǎn)生的特定語言代碼。下面給出thrift文件描述:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061

namespacecpp thrift.example namespacejava thrift.example enumTweetType { TWEET, RETWEET = 2, DM = 0xa, REPLY } structLocation { 1: required doublelatitude; 2: required doublelongitude; } structTweet { 1: required i32 userId; 2: required string userName; 3: required string text; 4: optional Location loc; 5: optional TweetType tweetType = TweetType.TWEET; 16: optional string language = "english"; } typedeflist<Tweet> TweetList structTweetSearchResult { 1: TweetList tweets; } consti32 MAX_RESULTS = 100; service Twitter { voidping(), boolpostTweet(1:Tweet tweet); TweetSearchResult searchTweets(1:string query); onewayvoidzip() }

(1) Java語言

(a)  產(chǎn)生的文件

一個單獨的文件(Constants.java)包含所有的常量定義。

每個結(jié)構(gòu)體,枚舉或者服務(wù)各占一個文件

$ tree gen-java

`– thrift

`– example

|– Constants.java

|– Location.java

|– Tweet.java

|– TweetSearchResult.java

|– TweetType.java

`– Twitter.java

(b)  類型

thrift將各種基本類型和容器類型映射成java類型:

12345678910111213141516171819bool: boolean byte: byte i16:short i32:int i64:long double:double string: String list<t1>: List<t1> set<t1>: Set<t1> map<t1,t2>: Map<t1, t2>

(c)  typedef

Java不支持typedef,它只使用原始類型,如,在上面的例子中,產(chǎn)生的代碼中,TweetSearchResult會被還原成list<Tweet> tweets

(d)  Enum

Thrift直接將枚舉類型映射成java的枚舉類型。用戶可以使用geValue方法獲取枚舉常量的值。此外,編譯器會產(chǎn)生一個findByValue方法獲取枚舉對應(yīng)的數(shù)值。

(e)  常量

Thrift把所有的常量放在一個叫Constants的public類中,每個常量修飾符是public static final。

(2)  C++語言

(a)  產(chǎn)生的文件

所有變量均存放在一個.cpp/.h文件對中

所有的類型定義(枚舉或者結(jié)構(gòu)體)存放到另一個.cpp/.h文件對中

每一個service有自己的.cpp/.h文件

$ tree gen-cpp

|– example_constants.cpp

|– example_constants.h

|– example_types.cpp

|– example_types.h

|– Twitter.cpp

|– Twitter.h

`– Twitter_server.skeleton.cpp

其他語言

Python,Ruby,Javascript

4.  實踐經(jīng)驗

thrift文件內(nèi)容可能會隨著時間變化的。如果已經(jīng)存在的消息類型不再符合設(shè)計要求,比如,新的設(shè)計要在message格式中添加一個額外字段,但你仍想使用以前的thrift文件產(chǎn)生的處理代碼。如果想要達到這個目的,只需:

(1)  不要修改已存在域的整數(shù)編號

(2)  新添加的域必須是optional的,以便格式兼容。對于一些語言,如果要為optional的字段賦值,需要特殊處理,比如對于C++語言,要為

123456789

structExample{ 1 : i32 id, 2 : string name, 3 : optional age, }

中的optional字段age賦值,需要將它的__isset值設(shè)為true,這樣才能序列化并傳輸或者存儲(不然optional字段被認為不存在,不會被傳輸或者存儲),

如:

123456789

Example example; ...... example.age=10, example.__isset.age = true;//__isset是每個thrift對象的自帶的public成員,來指定optional字段是否啟用并賦值。 ......

(3)  非required域可以刪除,前提是它的整數(shù)編號不會被其他域使用。對于刪除的字段,名字前面可添加“OBSOLETE_”以防止其他字段使用它的整數(shù)編號。

(4) thrift文件應(yīng)該是unix格式的(windows下的換行符與unix不同,可能會導致你的程序編譯不過),如果是在window下編寫的,可使用dos2unix轉(zhuǎn)化為unix格式。

(5)  貌似當前的thrift版本(0.6.1)不支持常量表達式的定義(如 const i32 DAY = 24 * 60 * 60),這可能是考慮到不同語言,運算符不盡相同。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 易门县| 河曲县| 东乌珠穆沁旗| 三穗县| 南充市| 青阳县| 宜州市| 峡江县| 台南县| 凤冈县| 寿光市| 泸定县| 固原市| 贺州市| 宁阳县| 海盐县| 庆云县| 京山县| 万山特区| 龙胜| 水城县| 河南省| 新邵县| 麻城市| 萝北县| 和平区| 祁连县| 喜德县| 花莲县| 鲁甸县| 广饶县| 阿城市| 临夏市| 涟源市| 沁阳市| 龙陵县| 宾阳县| 西昌市| 县级市| 宣化县| 乐东|