Thrift快速入門,thrift入門
Thrift 簡單樣本
2017-01-19 16:47:57
首先通過先面兩個樣本簡單感受一下Thrift(RPC)服務端與用戶端之間的通訊......
RPC學習----Thrift快速入門和Java簡單樣本
Thrift入門及Java執行個體示範
Thrift 是什嗎?
Thrift 源於大名鼎鼎的 facebook 之手,在 2007 年 facebook 提交 Apache 基金會將 Thrift 作為一個開源項目,對於當時的 facebook 來說創造 thrift 是為瞭解決 facebook 系統中各系統間大資料量的傳 輸通訊以及系統之間語言環境不同需要跨平台的特性。所以 thrift 可以支援多種程式語言,例如: C++, C#, Cocoa, Erlang, Haskell, Java, Ocami, Perl, PHP, Python, Ruby, Smalltalk. 在多種不同的語言之間通訊 thrift可以作為二進位的高效能的通訊中介軟體,支援資料(對象)序列化和多種類型的 RPC 服 務。Thrift 適用於程式對程 序靜態資料交換,需要先確定好他的資料結構,他是完全靜態化的,當資料結構發生變化時,必須重新編輯 IDL 檔案,代碼產生,再編譯載入的流程,跟其他 IDL 工具相比較可以視為是 Thrift 的弱項,Thrift 適用於搭建大型資料交換及儲存的通用工具,對於大型系統中的內部資料轉送相對於 JSON 和 xml 無論在效能、傳輸大小上有明顯的優勢。
Thrift 是 IDL(interface definition language)描述性語言的一個具體實現,關於 IDL的話題我們可以追溯到 CORBA 盛行 1999-2001 年(Common Object Request Broker Architecture/公用對象請求代理體繫結構),在 IDL 中我們似乎不會忘記到這幾個關鍵字:module、interface、string、long 和 int,我還記得 IDL 利用 module來建立名稱空間,並且準確地映射為 Java 的 package,這些特性幾乎和現在 thrift的特性完全相同,所以 thrift 的設計思想和理念絕不是什麼從火星來的 new idea,看看在那個 CORBA 盛行的年代人們提出的概念, CORBA 請求的各個部分,回頭我們再與 thrift 進行對比一下:
Thrift 基礎架構
Thrift 是一個服務端和用戶端的架構體系,從我個人的感官上來看 Thrift 是一個類似XML-RPC+Java-to- IDL+Serialization Tools=Thrift 的東東,Thrift 具有自己內部 定義的傳輸協議規範(TProtocol)和傳輸資料標準(TTransports),通過 IDL 指令碼對傳輸資料的資料結構(struct) 和傳輸資料的商務邏輯(service)根據不同的運行環境快速的 構建相應的代碼,並且通過自己內部的序列化機制對傳輸的資料進行簡化和壓縮提高高並發、 大型系統中資料互動的成本,描繪了 Thrift 的整體架構,分為 6 個部分:
圖中前面 3 個部分是 1.你通過 Thrift 指令檔產生的程式碼,2.圖中的褐色框部分是你根據產生代碼構建的用戶端和處理器的代碼,3.圖中紅色的部分是 2 端產生的計算結 果。從 TProtocol 下面 3 個部分是 Thrift 的傳輸體系和傳輸協議以及底層 I/O 通訊,Thrift 並且提供 堵塞、非阻塞,單線程、多線程的模式運行在伺服器上,還可以配合 伺服器/容器一起運行,可以和現有 JEE 伺服器/Web 容器無縫的結合。
Thrift 基礎資料型別 (Elementary Data Type)
bool:布爾值,true 或 false,對應 Java 的 boolean
byte:8 位有符號整數,對應 Java 的 byte
i16:16 位有符號整數,對應 Java 的 short
i32:32 位有符號整數,對應 Java 的 int
i64:64 位元有符號整數,對應 Java 的 long
double:64 位元浮點數,對應 Java 的 double
string:utf-8編碼的字串,對應 Java 的 String
struct:定義公用的對象,類似於 C 語言中的結構體定義,在 Java 中是一個 JavaBean
list:對應 Java 的 ArrayList
set:對應 Java 的 HashSet
map:對應 Java 的 HashMap
exception:對應 Java 的 Exception
service:對應服務的類
Thrift 資料轉送協議
Thrift 可以讓你選擇用戶端與服務端之間傳輸通訊協定的類別,在傳輸協議上總體上劃分為文本(text)和二進位(binary)傳輸協議, 為節約頻寬,提供傳輸效率,一般情況下 使用二進位類型的傳輸協議為多數,但有時會還是會使用基於文本類型的協議,這需要根據項目/產品中的實際需求。
TBinaryProtocol–二進位編碼格式進行資料轉送
TCompactProtocol–這種協議非常有效,使用 Variable-Length Quantity(VLQ) 編碼對資料進行壓縮
TJSONProtocol–使用 JSON 的資料編碼協議進行資料轉送
TSimpleJSONProtocol–這種節約只提供 JSON 唯寫的協議,適用於通過指令碼語言解析
TDebugProtocol–在開發的過程中協助開發人員調試用的,以文本的形式展現方便閱讀
Thrift 傳輸層
TSocket-使用堵塞式 I/O 進行傳輸,也是最常見的模式
TFramedTransport-使用非阻塞方式,按塊的大小,進行傳輸,類似於 Java 中的 NIO
TFileTransport-顧名思義按照檔案的方式進程傳輸,雖然這種方式不提供 Java 的實現,但是實現起來非常簡單
TMemoryTransport-使用記憶體 I/O,就好比 Java 中的 ByteArrayOutputStream實現
TZlibTransport- 使用執行 zlib 壓縮,不提供 Java 的實現
Thrift 服務端類型
TSimpleServer-單線程伺服器端使用標準的堵塞式 I/O
TThreadPoolServer-多線程伺服器端使用標準的堵塞式 I/O
TNonblockingServer–多線程伺服器端使用非堵塞式 I/O,並且實現了 Java 中的 NIO 通道
Thrift 與其他傳輸方式的比較
XML 與 JSON 相比體積太大,但是 XML 傳統,也不算複雜。JSON 體積較小,新穎,但不夠完善。Thrift 體積超小,使用起來比較麻煩,不如前兩者輕便,但是對於 1.高並發、2.資料傳 輸量大、3.多語言環境, 滿足其中 2 點使用 thrift 還是值得的。
服務端編碼基本步驟:用戶端編碼基本步驟:
tips:用戶端和服務端的協議要一致
Thrift介面檔案書寫
建立檔案並命名為demoHello.thrift
1 namespace java com.unionpay.thrifttest2 3 service HelloWorldService{4 string sayHello(1:string username)5 }View Code
Thrift介面檔案編譯
1 thrift -r -gen java demoHello.thrift
Java服務端代碼及解釋
1 import org.apache.thrift.protocol.TCompactProtocol; 2 import org.apache.thrift.server.TServer; 3 import org.apache.thrift.server.TSimpleServer; 4 import org.apache.thrift.transport.TServerSocket; 5 import org.apache.thrift.transport.TServerTransport; 6 7 public class HelloServerDemo { 8 9 //定義服務連接埠號碼10 public static final int SERVER_PORT = 8090;11 12 public static void main(String[] args){13 HelloServerDemo service = new HelloServerDemo();14 service.startServer();15 }16 17 public void startServer(){18 try{19 System.out.println("HelloWorld TSimpleServer start...");20 21 /* thrift Processor 商務邏輯處理層22 建立Processor,HelloWorldImpl 實作類別作為參數傳入Processor構造方法裡23 processor主要完成的事情:24 1.把idl裡定義的方法進行封裝,最終暴露出一個統一的介面給thrift server進行調用25 2.封裝protocol和transport層,包括輸入輸出資料流的處理細節、序列化還原序列化*/ 26 HelloWorldService.Processor<HelloWorldService.Iface> tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>(new HelloWorldImpl());27 28 //建立TServerTransport29 TServerTransport serverTransport = new TServerSocket(SERVER_PORT);30 TServer.Args tArgs = new TServer.Args(serverTransport);31 tArgs.processor(tprocessor);32 //建立TProtocol33 tArgs.protocolFactory(new TCompactProtocol.Factory());34 //建立TServer35 TServer server = new TSimpleServer(tArgs);36 //啟動TServer37 server.serve();38 }catch(Exception e){39 System.out.println("Server start error!");40 e.printStackTrace();41 }42 }43 }View Codejava用戶端代碼實現及解釋
1 import org.apache.thrift.TException; 2 import org.apache.thrift.protocol.TCompactProtocol; 3 import org.apache.thrift.protocol.TProtocol; 4 import org.apache.thrift.transport.TSocket; 5 import org.apache.thrift.transport.TTransport; 6 import org.apache.thrift.transport.TTransportException; 7 8 /** 9 * @author jxwch 10 * @date 2017.01.1711 *12 */13 public class HelloClientDemo {14 15 //定義Socket服務參數16 public static final String SERVER_IP = "localhost";17 public static final int SERVER_PORT = 8090;18 public static final int TIMEOUT = 30000;19 20 21 public static void main(String[] args){22 HelloClientDemo client = new HelloClientDemo();23 client.startClient("jxwch");24 }25 26 public void startClient(String userName){27 28 29 TTransport transport = null;30 try{31 //建立TTransport32 transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT);33 //建立TProtocol34 TProtocol protocol = new TCompactProtocol(transport);35 //建立Client36 HelloWorldService.Client client = new HelloWorldService.Client(protocol);37 //啟動TTransport38 transport.open();39 40 //調用client中封裝的方法41 String result = client.sayHello(userName);42 System.out.println("Thrift Client result: " + result);43 }catch(TTransportException e){44 e.printStackTrace();45 }catch(TException e){46 e.printStackTrace();47 }finally{48 if(null != transport){49 transport.close();50 }51 }52 }53 }View CodeThriftDemo樣本下載
樣本源碼下載