1. 程式人生 > >Thrift介紹加DEMO解析

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.執行結果

執行服務端結果:


執行客戶端結果:


測試通過,符合預想。

宣告:本文主要來自網上整理 程式程式碼中的解析為個人理解  如有錯誤 請指出  歡迎交流