Thrift教程初級篇——thrift安裝環境變量配置第一個實例


前言:                    

因為項目需要跨語言,c++客戶端,web服務端,遠程調用等需求,所以用到了RPC框架Thrift,剛開始有點虛,第一次接觸RPC框架,后來沒想到Thrift開發方便上手快,而且性能和穩定性也不錯,項目也順利完成。所以給各位小白們,“科普”一下如何使用Thrift完成自己的遠程調用。

1.什么是RPC:                     

 

平時開發的服務,大多都是本地調用,如果說需要依賴他人服務了,而且他人的服務在遠端,那怎么調用呢?

 

RPC能夠游刃有余的解決這樣的問題。首先來研究一下什么RPC

 

RPC(remote produce call),遠程過程調用協議。它是一種通過網絡從遠程計算機程序上請求服務,而不需要了解底層網絡技術的協議。

 

看下面這張圖:

一次遠程的調用經歷了一下10個步驟:

1.調用客戶端以本地方式調用遠程服務

2.client stub將請求(方法和參數)組裝成網絡消息

3.client stub找得到服務器地址,將消息傳送到遠程主機

4.server stub得到傳送過來的請求,進行解碼

5.server stub 調用本地服務,處理請求

6.本地服務處理請求,並將處理結果返回給server stub

7.server stub將請求處理結果組裝成網絡消息

8.server stub找到客戶端地址,將請求處理結果傳送給客戶端

9.client stub 接收到請求處理結果,進行解碼

10.客戶端最終接收到請求處理結果

 

RPC框架的目的就是將2-9步驟封裝起來,對使用者透明,客戶端只需要執行第一步調用接口,然后就能夠得到結果。這樣是不是很方便,而且省去了很多麻煩。

 

通過對RPC的初步了解,那接下來就開始不如Thrift的大門吧

 

2.What is Thrift?                                                

ThriftFacebook公司開發的一款開源的RPC框架,對於一般的RPC框架來說,通過IDL語言定義接口(Interface description language),Thrift也采用了這樣的做法,並通過一個編譯器生成不同語言的代碼(目前支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, SmalltalkOCaml,並由生成的代碼負責RPC協議層和傳輸層的實現。

Thrift協議棧:

第一部分(Your Code):

簡單總結:開發者的業務邏輯代碼

 

第二部分(ServiceClient

Thrift自動生成的代碼,包含ProcessorTserverServiceClient

TServer負責接收Client的請求,並將請求轉發到Processor進行處理。TServer主要任務就是高效的接受Client的請求,特別是在高並發請求的情況下快速完成請求。

Processor(或者TProcessor)負責對Client的請求做出相應,包括RPC請求轉發,調用參數解析和用戶邏輯調用,返回值寫回等處理步驟。Processor是服務器端從Thrift框架轉入用戶邏輯的關鍵流程。Processor同時也負責向Message結構中寫入數據或者讀出數據。

ServiceClient就是客戶端,包含可以調用的請求方法和發送客戶端請求

 

第三部分:

TProtocol主要負責結構化數據組裝成Message,或者從Message結構中讀出結構化數據。TProtocol將一個有類型的數據轉化為字節流以交給TTransport進行傳輸,或者從TTransport中讀取一定長度的字節數據轉化為特定類型的數據。如int32會被TBinaryProtocol Encode為一個四字節的字節數據,或者TBinaryProtocolTTransport中取出四個字節的數據Decodeint32

 

第四部門:

TTransport負責以字節流方式發送和接收Message,是底層IO模塊在Thrift框架中的實現,每一個底層IO模塊都會有一個對應TTransport來負責Thrift的字節流(Byte Stream)數據在該IO模塊上的傳輸。例如TSocket對應Socket傳輸,TFileTransport對應文件傳輸。

 

第五部分:

底層IO模塊,負責實際的數據傳輸,包括Socket,文件,或者壓縮數據流等。

 

通過這個協議棧,可以得出結論,使用Thrift只需要做三件事:

1.通過IDL定義數據結構和服務

2.利用代碼生成工具生成代碼

3.編寫你的業務邏輯

 

接下來我們就按照這個三步走開發一個簡單的HelloWorld級別的客戶端與服務端

 

3.How to use Thrift?                                                

首先要做的就是下載並配置Thrift,附上鏈接:http://thrift.apache.org/download

現在版本都是0.10.0,

下載好之后將名字改成“thrift.exe”

我的電腦操作系統是Windows,屬於在Windows情況下配置。

thrift.exe放在Thrift文件夾下:

配置環境變量:

 

配置完成之后,打開dos窗口,輸入”thrifx -version”:

接下來執行三步走策略:

 

第一步:通過IDL定義數據結構和服務                

從最簡單的HelloWorld開始,編寫HelloWorld.thrift,內容如下:

namespace java service.server
service HelloWorld{
    string sendString(1:string para)
}

隨便放在一個文件夾下,我這里放在E:\software\Thrift,

 第二步:利用代碼生成工具生成代碼                                   

進入HelloWorld.thrift所在目錄,執行

執行完成,你會發現沒有任何提示,記得有位大神說過,沒有任何提示就是好事。

這時候發現在當前目錄下多了一個gen-java的目錄,里面有Thrift生成的HelloWorld.java

OK,前兩步已經完成,還是很簡單的吧。

第三步:編寫你的業務邏輯                       

創建一個Gradle管理的Java項目,bulid.gradle中添加相關的依賴,將gen-java中的HelloWorld.java拷貝到IDE的java項目中(注意包名,地址對應)。

(喜歡用Maven的朋友可以用Maven構建)

dependencies {
	compile "org.apache.thrift:libthrift:0.9.2"
	compile "org.slf4j:slf4j-log4j12:1.7.5"
}

 

 創建HelloWorldServiceImpl實現HelloWorld.Iface接口,這個就是主要的業務邏輯。

package service.impl;

import org.apache.thrift.TException;
import service.server.HelloWorld;

/**
 * 服務端實現
 * 
 * @author tang
 */
public class HelloWorldServiceImpl implements HelloWorld.Iface {

	@Override
	public String sendString(String para) throws TException {
		System.out.println("接收到服務端傳來的參數: " + para);
		String result = "服務端成功收到消息";
		return result;
	}

}

 接着,創建服務端實現代碼,命名為HelloWorldServiceServer,把HelloWoeldServiceImpl作為一個具體的處理器傳遞給Thrift服務器:

 

package service.server;

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 org.apache.thrift.transport.TTransportException;
/**
 * 服務端
 * 
 * @author tang
 */
import service.impl.HelloWorldServiceImpl;

public class HelloWorldServiceServer {

	public static void main(String[] args) throws TTransportException {
		System.out.println("服務端開啟");

		// 關聯處理器
		TProcessor tProcessor = new HelloWorld.Processor<HelloWorld.Iface>(new HelloWorldServiceImpl());

		// 設置服務端口為 8080
		TServerSocket serverSocket = new TServerSocket(8080);

		// 簡單的單線程服務模型
		TServer.Args tArgs = new TServer.Args(serverSocket);
		tArgs.processor(tProcessor);
		// 設置協議工廠為 TBinaryProtocol.Factory
		tArgs.protocolFactory(new TBinaryProtocol.Factory());
		TServer server = new TSimpleServer(tArgs);
		// 啟動服務
		server.serve();
	}

}

 最后,再寫一個客戶端HelloWorldClient.java:

package client;

import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import service.server.HelloWorld;

/**
 * 客戶端
 * 
 * @author tang
 */
public class HelloWorldClient {

	public static void main(String[] args) {
		System.out.println("客戶端啟動....");
		TTransport transport = null;
		try {
			// 設置調用的服務地址為本地,端口為8080,超時設置為30秒
			transport = new TSocket("localhost", 8080, 30000);
			// 協議要和服務端一致
			TProtocol protocol = new TBinaryProtocol(transport);
			HelloWorld.Client client = new HelloWorld.Client(protocol);
			transport.open();
			// 調用接口方法
			String result = client.sendString("Hello World!");
			System.out.println(result);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (null != transport) {
				transport.close();
			}
		}
	}

}

 這個是project結構圖:

這里有一些Thrift自帶的警告,不用去管他(有點違背Effective java中的原則)。。。。。

最后的最后:測試                                                                                            

啟動服務端,然后再啟動客戶端,這是服務端會收到來自客戶端的消息:“HelloWorld”

客戶端收到服務端的反饋:

好了,到這里,Thrift的第一個實例就結束了,總的來說Thrift還是很好用的,有些的不好的地方歡迎批評斧正!

參考文章:

 http://www.blogjava.net/ldwblog/archive/2014/12/03/421011.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM