1 前言
Thrift是facebook技術核心框架之一,不同開發語言開發的服務可以通過該框架實現通信。Thrift通過接口定義語言 (interface definition language,IDL) 來定義數據類型和服務,Thrift接口定義文件由Thrift代碼編譯器生成thrift目標語言的代碼(目前支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk和OCaml),並由生成的代碼負責RPC協議層和傳輸層的實現。
簡而言之,開發者只需準備一份thrift腳本,通過thrift code generator(像gcc那樣輸入一個命令)就能生成所要求的開發語言代碼。不支持windows。
Thrift側重點是構建跨語言的可伸縮的服務,特點就是支持的語言多,同時提供了完整的RPC service framework,可以很方便的直接構建服務,不需要做太多其他的工作。服務端可以根據需要編譯成simple | thread-pool | threaded | nonblocking等方式;
本文檔參考:Thrift types, Thrift IDL, Thrift:The Missing Guide.
2 語法參考
2.1 類型
Thrift類型系統包括預定義基本類型,用戶自定義結構體,容器類型,異常和服務定義。
2.1.1 基本類型
-
bool: 布爾值 (true or false), one byte
-
byte: 有符號字節
-
i16: 16位有符號整型
-
i32: 32位有符號整型
-
i64: 64位有符號整型
-
double: 64位浮點型
-
string: Encoding agnostic text or binary string
Note that: Thrift不支持無符號整型,因爲Thrift目標語言沒有無符號整型,無法轉換。
2.1.2 容器(Containers)
Thrift容器與流行編程語言的容器類型相對應,採用Java泛型風格。它有3種可用容器類型:
-
list<t1>: 元素類型爲t1的有序表,容許元素重複。(有序表ordered list不知道如何理解?排序的?c++的vector不排序)
-
set<t1>:元素類型爲t1的無序表,不容許元素重複。
-
map<t1,t2>: 鍵類型爲t1,值類型爲t2的kv對,鍵不容許重複。
容器中元素類型可以是除了service外的任何合法Thrift類型(包括結構體和異常)。
2.1.3 結構體和異常(Structs and Exceptions)
Thrift結構體在概念上類似於(similar to)C語言結構體類型--將相關屬性封裝在一起的簡便方式。Thrift結構體將會被轉換成面嚮對象語言的類。
異常在語法和功能上類似於(equivalent to)結構體,差別是異常使用關鍵字exception而不是struct聲明。但它在語義上不同於結構體:當定義一個RPC服務時,開發者可能需要聲明一個遠程方法拋出一個異常。
結構體和異常的聲明將在下一節介紹。
2.1.4 服務(Services)
服務的定義方法在語義(semantically)上等同於面嚮對象語言中的接口。Thrift編譯器會產生執行這些接口的client和server stub。具體參見下一節。
2.2 類型定義(Typedef)
Thrift支持C/C++類型定義。
typedef i32 MyInteger // a typedef T ReT // b
說明:a. 末尾沒有逗號。b. struct也可以使用typedef。
2.3 枚舉(Enums)
很多語言都有枚舉,意義都一樣。比如,當定義一個消息類型時,它只能是預定義的值列表中的一個,可以用枚舉實現。
enum TweetType {TWEET, // (1) RETWEET = 2, // (2)DM = 0xa, // (3) REPLY} // (4)struct Tweet {1: required i32 userId;2: required string userName;3: required string text;4: optional Location loc;5: optional TweetType tweetType = TweetType.TWEET; // (5)16: optional string language = "english"}
說明:
(1). 編譯器默認從0開始賦值
(2). 可以賦予某個常量某個整數
(3). 允許常量是十六進制整數
(4). 末尾沒有分號
(5). 給常量賦缺省值時,使用常量的全稱
注意,不同於protocal buffer,thrift不支持枚舉類嵌套,枚舉常量必須是32位的正整數
2.4 註釋(Comment)
Thrift支持shell風格, C多行風格和Java/C++單行風格。
# This is a valid comment.// C++/Java style single-line comments work just as well.
2.5 名字空間(Namespace)
Thrift中的命名空間類似於C++中的namespace和java中的package,它們提供了一種組織(隔離)代碼的簡便方式。名字空間也可以用於解決類型定義中的名字衝突。
由於每種語言均有自己的命名空間定義方式(如python中有module), thrift允許開發者針對特定語言定義namespace:
namespace cpp com.example.project // (1)namespace java com.example.project // (2)namespace php com.example.project
(1). 轉化成namespace com { namespace example { namespace project {
(2). 轉換成package com.example.project
2.6 Includes
便於管理、重用和提高模塊性/組織性,我們常常分割Thrift定義在不同的文件中。包含文件搜索方式與c++一樣。Thrift允許文件包含其它thrift文件,用戶需要使用thrift文件名作爲前綴訪問被包含的對象,如:
include "tweet.thrift" // (1)...struct TweetSearchResult {1: tweet.Tweet tweet; // (2)}
說明:
(1). thrift文件名要用雙引號包含,末尾沒有逗號或者分號
(2). 注意tweet前綴
2.7 常量(Constant)
Thrift允許定義跨語言使用的常量,複雜的類型和結構體可使用JSON形式表示。
const i32 INT_CONST = 1234; // (1)
說明:
(1) 分號可有可無。支持16進制。
2.8 結構體定義(Defining Struct)
struct是Thrift IDL中的基本組成塊,由域組成,每個域有唯一整數標識符,類型,名字和可選的缺省參數組成。如定義一個類似於Twitter服務:
struct Tweet {1: required i32 userId; // (1)2: required string userName; // (2)3: required string text;4: optional Location loc; // (3)16: optional string language = "english" // (4)}struct Location { // (5)1: required double latitude;2: required double longitude;}
(1) 每個域有一個唯一的正整數標識符;
(2) 每個域可標識爲required或optional;
(3) 結構體可以包含其它結構體
(4) 域可有默認值,與required或optional無關。
(5) Thrift文件可以定義多個結構體,並在同一文件中引用,也可加入文件限定詞在其它Thrift文件中引用。
如上所見,消息定義中的每個域都有一個唯一數字標籤,這些數字標籤在傳輸時用來確定域,一旦使用消息類型,標籤不可改變。(隨着項目的進展,可以要變更Thrift文件,最好不要改變原有的數字標籤)
規範的struct定義中的每個域均會使用required或者optional關鍵字進行標識。如果required標識的域沒有賦值,Thrift將給予提示;如果optional標識的域沒有賦值,該域將不會被序列化傳輸;如果某個optional標識域有缺省值而用戶沒有重新賦值,則該域的值一直爲缺省值;如果某個optional標識域有缺省值或者用戶已經重新賦值,而不設置它的__isset爲true,也不會被序列化傳輸。(不被序列化傳輸的後果是什麼?爲空爲零?還是默認值,下次試試)
與services不同,結構體不支持繼承。
2.9 服務定義(Defining Services)
在流行的序列化/反序列化框架(如protocal buffer)中,Thrift是少有的提供多語言間RPC服務的框架。這是Thrift的一大特色。
Thrift編譯器會根據選擇的目標語言爲server產生服務接口代碼,爲client產生stubs。
service Twitter {// A
method definition looks like C code. It has a return type, arguments,// and
optionally a list of exceptions that it may throw. Note that argument// lists
and exception list are specified using the exact same syntax as// field
lists in structs.void ping(), // (1)bool postTweet(1:Tweet
tweet); // (2)TweetSearchResult
searchTweets(1:string query); // (3)// The
'oneway' modifier indicates that the client only makes a request and// does
not wait for any response at all. Oneway methods MUST be void.oneway void zip() // (4)}
(1) 有點亂,接口支持以逗號和分號結束;
(2) 參數可以是基本類型和結構體;(參數是cosnt的,轉換爲c++語言是const&)
(3) 返回值同參數一樣;
(4) 返回值是void,注意oneway;
Note that:參數列表的定義與結構體一樣。服務支持繼承。
源地址:http://www.cnblogs.com/tianhuilove/archive/2011/09/05/2167669.html