麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

Thrift使用指南

2019-11-11 05:44:57
字體:
來源:轉載
供稿:網友
轉載自:董的博客 http://dongxicheng.org/search-engine/thrift-guide/

1. 內容概要

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

2. 語法參考

2.1 Types

Thrift類型系統包括預定義基本類型,用戶自定義結構體,容器類型,異常和服務定義

(1) 基本類型

12345678910111213

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

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

(2) 容器類型

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

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

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

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

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

(3)  結構體和異常

Thrift結構體在概念上同C語言結構體類型—— 一種將相關屬性聚集(封裝)在一起的方式。在面向對象語言中,thrift結構體被轉換成類。

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

結構體和異常的聲明將在下一節介紹。

(4)  服務

服務的定義方法在語法上等同于面向對象語言中定義接口。Thrift編譯器會產生實現這些接口的client和server樁。具體參見下一節。

(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.  可以賦予某個常量某個整數

c.  允許常量是十六進制整數

d.  末尾沒有逗號

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

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

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允許開發者針對特定語言定義namespace:

123

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

說明:

a.  轉化成namespace com { namespace example { namespace project {

b.  轉換成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允許用戶定義常量,復雜的類型和結構體可使用JSON形式表示。

123

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

說明:

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

2.7   定義結構體

結構體由一系列域組成,每個域有唯一整數標識符,類型,名字和可選的缺省參數組成。如:

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.  每個域有一個唯一的,正整數標識符

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

c.  結構體可以包含其他結構體

d.  域可以有缺省值

e.  一個thrift中可定義多個結構體,并存在引用關系

規范的struct定義中的每個域均會使用required或者optional關鍵字進行標識。如果required標識的域沒有賦值,thrift將給予提示。如果optional標識的域沒有賦值,該域將不會被序列化傳輸。如果某個optional標識域有缺省值而用戶沒有重新賦值,則該域的值一直為缺省值。

與service不同,結構體不支持繼承,即,一個結構體不能繼承另一個結構體。

2.8   定義服務

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

Thrift編譯器會根據選擇的目標語言為server產生服務接口代碼,為client產生樁代碼。

1234567891011121314151617181920

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

說明:

a. 函數定義可以使用逗號或者分號標識結束

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

c. 返回值可以是基本類型或者結構體

d. 返回值可以是void

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

Service支持繼承,一個service可使用extends關鍵字繼承另一個service

3.  產生代碼

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

概念

Thrift的網絡棧如下所示:

3.1   Transport

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

123456789

open close read write flush

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

1234567

open listen accept close

3.2   Protocol

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

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封裝了從輸入數據流中讀數據和向數據數據流中寫數據的操作。讀寫數據流用Protocol對象表示。Processor的結構體非常簡單:

12345

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

與服務相關的processor實現由編譯器產生。Processor主要工作流程如下:從連接中讀取數據(使用輸入protocol),將處理授權給handler(由用戶實現),最后將結果寫到連接上(使用輸出protocol)。

3.4   Server

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

(1)  創建一個transport對象

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

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

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

3.5   應用舉例

下面,我們討論thrift文件產生的特定語言代碼。下面給出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)  產生的文件

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

每個結構體,枚舉或者服務各占一個文件

$ 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,它只使用原始類型,如,在上面的例子中,產生的代碼中,TweetSearchResult會被還原成list<Tweet> tweets

(d)  Enum

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

(e)  常量

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

(2)  C++語言

(a)  產生的文件

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

所有的類型定義(枚舉或者結構體)存放到另一個.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.  實踐經驗

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

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

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

123456789

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

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

如:

123456789

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

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

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

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


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 久久久入口 | 久久久久久久久久亚洲 | 黄色网址电影 | 91精品国产99久久久久久红楼 | 日本精品中文字幕 | 色综合狠狠 | 午夜在线视频一区二区三区 | 欧美日韩专区国产精品 | 色中色在线播放 | 久久毛片免费观看 | 草草视频在线播放 | 黑人操穴| 欧美黄色一级片在线观看 | 久久精品欧美视频 | 羞羞色院91精品网站 | 久久久久免费电影 | 亚洲最新黄色网址 | 亚洲综合一区在线观看 | 91九色网址 | 毛片视频网站在线观看 | 黄色片免费在线播放 | 国产成人自拍av | av在线不卡免费 | av黄色片网站 | 国产精品视频久 | 成年人国产视频 | 久久国产精品系列 | 在线观看免费视频麻豆 | 一区二区久久久久草草 | 欧美精品一区二区三区在线播放 | 国产精品久久久久久久久久东京 | 久久污 | 欧美1—12sexvideos | 精品国产99久久久久久宅男i | 免费看成年人视频在线 | 中文字幕亚洲欧美 | 中文字幕在线免费看 | 水卜樱一区二区av | 黄色一级片免费观看 | 日韩视频一二区 | 欧美黄色免费视频 |