Thrift介紹加DEMO解析
1、Thrift簡介
Thrift是一個跨語言的服務部署框架,最初由Facebook於2007年開發,2008年進入Apache開源專案。Thrift通過一箇中間語言(IDL, 介面定義語言)來定義RPC的介面和資料型別,然後通過一個編譯器生成不同語言的程式碼(目前支援C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa,Smalltalk和OCaml),並由生成的程式碼負責RPC協議層和傳輸層的實現。
主要分為六個部分1.你的業務邏輯實現(You Code) 2.客戶端和服務端對應的Service 3.執行讀寫操作的計算結果4.TProtocol5.TTransports 6.底層I/O通訊。
2、Thrift語法
參考董的部落格,地址:http://dongxicheng.org/search-engine/thrift-guide/
3、基本知識簡介
來源網址:http://www.javabloger.com/article/apache-thrift-architecture.html
a)資料型別
* Base Types:基本型別
* Struct:結構體型別
* Container:容器型別,即List、Set、Map
* Exception:異常型別
* Service: 定義物件的介面,和一系列方法
b)協議
Thrift可以讓你選擇客戶端與服務端之間傳輸通訊協議的類別,在傳輸協議上總體上劃分為文字(text)和二進位制(binary)傳輸協議, 為節約頻寬,提供傳輸效率,一般情況下使用二進位制型別的傳輸協議為多數,但有時會還是會使用基於文字型別的協議,這需要根據專案/產品中的實際需求:
*TBinaryProtocol – 二進位制編碼格式進行資料傳輸。
*TCompactProtocol – 這種協議非常有效,使用Variable-Length Quantity (VLQ) 編碼對資料進行壓縮。
*TJSONProtocol – 使用JSON的資料編碼協議進行資料傳輸。
*TSimpleJSONProtocol – 這種節約只提供JSON只寫的協議,適用於通過指令碼語言解析
*TDebugProtocol – 在開發的過程中幫助開發人員除錯用的,以文字的形式展現方便閱讀。
c)傳輸層
*TSocket- 使用堵塞式I/O進行傳輸,也是最常見的模式。
*TFramedTransport- 使用非阻塞方式,按塊的大小,進行傳輸,類似於Java中的NIO。
*TFileTransport- 顧名思義按照檔案的方式程序傳輸,雖然這種方式不提供Java的實現,但是實現起來非常簡單。
*TMemoryTransport- 使用記憶體I/O,就好比Java中的ByteArrayOutputStream實現。
*TZlibTransport- 使用執行zlib壓縮,不提供Java的實現。
d)服務端型別
*TSimpleServer - 單執行緒伺服器端使用標準的堵塞式I/O。
*TThreadPoolServer - 多執行緒伺服器端使用標準的堵塞式I/O。
*TNonblockingServer – 多執行緒伺服器端使用非堵塞式I/O,並且實現了Java中的NIO通道。
e)Thrift與其他傳輸方式的比較
xml與JSON相比體積太大,但是xml傳統,也不算複雜。
json 體積較小,新穎,但不夠完善。
thrift 體積超小,使用起來比較麻煩,不如前兩者輕便,但是對於1.高併發、2.資料傳輸量大、3.多語言環境, 滿足其中2點使用 thrift還是值得的。
4.Thrift DEMO
第一步,編寫thrift內容 這裡主要是定義介面
DemoHello.thrift內容:
namespace java com.lza.thrift
service HelloWorldService{
stringsayHello(1:string username)
}
第二步,利用thrift編譯工具將thrift文字編譯成對應語言的文字,這裡編譯為JAVA。WINDOWS下的編譯工具為thrift-0.8.0.exe
命令格式:thrift-0.8.0.exe-r -gen java ./DemoHello.thrift
這樣就會在thrfit-0.8.0.exe所在目錄下生成一個資料夾,如圖一所示。
(圖一)
第三步,進行服務端和客戶端程式設計。
生成的HelloWorldService.java檔案一般不要去修改,除非你已經清楚的知道原理。這個檔案中主要是提供了一些服務端和客戶端進行互動的介面,並提供同步和非同步兩種介面。
1)服務端編碼的基本步驟:
實現服務處理介面impl
建立TProcessor
建立TServerTransport
建立TProtocol
建立TServer
啟動Server
2)客戶端編碼基本步驟:
建立Transport
建立TProtocol
基於TTransport和TProtocol建立 Client
呼叫Client的相應方法
3)介面實現程式碼:
package com.lza.thrift;
import org.apache.thrift.TException;
import com.lza.thrift.HelloWorldService;
/**
* 實現介面
* @author Administrator
*
*/
public class HelloWorldImpl implements HelloWorldService.Iface {
/**
* 根據傳入的使用者名稱向用戶問好
*/
@Override
public String sayHello(String username) throws TException {
// TODO Auto-generated method stub
String resultStr="Hi,"+"Welcome to our company !"+username;
return resultStr;
}
}
4)服務端程式碼:
package com.lza.thrift;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import com.lza.thrift.HelloWorldService;
import com.lza.thrift.HelloWorldImpl;
/**
* 編寫服務端程式碼
* @author Administrator
*
*/
public class HelloWorldServerDemo {
public static final int SERVER_PORT=8090;
/**
* 啟動服務函式
*/
public void startServe(){
try{
System.out.println("Hello World TSimpleServer start....");
/**
* 通過介面實現類去例項化資料流介面
* TProcessor介面的功能是封裝了資料流的讀寫操作 讀寫資料流用Protocol物件表示
* TProcessor介面結構
* interface TProcessor{
* bool process(TProtocol in,TProtocol out) throws TException
* }
*/
TProcessor tpprocessor=new HelloWorldService.Processor(new HelloWorldImpl());
/**
* 例項化服務埠
*/
TServerSocket serverTransport=new TServerSocket(SERVER_PORT);
/**
* 建立TServer引數物件
*/
TServer.Args tArgs=new TServer.Args(serverTransport);
/**
* 指定資料流讀寫物件
*/
tArgs.processor(tpprocessor);
/**
* 指定資料傳輸協議為二進位制
*/
tArgs.protocolFactory(new TBinaryProtocol.Factory());
/**
* 建立服務物件 單執行緒用TSimpleServer 多執行緒用TNonblockingServerSocket或者TThreadPoolServer
*/
TServer server=new TSimpleServer(tArgs);
/**
* 呼叫thrift生成JAVA檔案中的serve()函式
*/
server.serve();
}catch(Exception e){
System.out.println("Server start error!!");
e.printStackTrace();
}
}
public static void main(String args[]){
HelloWorldServerDemo server=new HelloWorldServerDemo();
server.startServe();
}
}
5)客戶端程式碼:
package com.lza.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 Administrator
*
*/
public class HelloWorldClientDemo {
public static final String SERVER_IP="localhost";
public static final int SERVER_PORT=8090;
public static final int TIMEOUT=30000;
/**
* 客戶端實現函式
* @param username 傳入的使用者名稱稱
*/
public void startClient(String username){
/**
* 建立傳輸物件
*/
TTransport transport=null;
try{
/**
* 根據服務端地址、服務埠、超時限制等引數實現化傳輸類TSocket
* 詳細解析參考:http://blog.csdn.net/qiangweiloveforever/article/details/9474941
* 傳輸方式必須與服務端一致
*/
transport=new TSocket(SERVER_IP,SERVER_PORT,TIMEOUT);
/**
* 設定傳輸協議 必須和服務端一致
*/
TProtocol protocol=new TBinaryProtocol(transport);
/**
* 例項化客戶端物件
*/
HelloWorldService.Client client=new HelloWorldService.Client(protocol);
/**
* 與服務端開始傳輸通訊
*/
transport.open();
/**
* 通過客戶端物件向服務端進行介面呼叫請求,並返回呼叫結果
*/
String result=client.sayHello(username);
System.out.println("Thrifty client result="+result);
}catch(Exception e){
e.printStackTrace();
}finally{
if(transport!=null){
transport.close();
}
}
}
public static void main(String args[]){
HelloWorldClientDemo client=new HelloWorldClientDemo();
client.startClient("LZA");
}
}
5.執行結果
執行服務端結果:
執行客戶端結果:
測試通過,符合預想。
宣告:本文主要來自網上整理 程式程式碼中的解析為個人理解 如有錯誤 請指出 歡迎交流