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

前言:                    

由於項目須要跨語言,c++客戶端,web服務端,遠程調用等需求,因此用到了RPC框架Thrift,剛開始有點虛,第一次接觸RPC框架,後來沒想到Thrift開發方便上手快,並且性能和穩定性也不錯,項目也順利完成。因此給各位小白們,「科普」一下如何使用Thrift完成本身的遠程調用。html

1.什麼是RPC:                     

 

平時開發的服務,大多都是本地調用,若是說須要依賴他人服務了,並且他人的服務在遠端,那怎麼調用呢?java

 

RPC可以遊刃有餘的解決這樣的問題。首先來研究一下什麼RPCc++

 

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

 

看下面這張圖:apache

一次遠程的調用經歷了一下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

相關文章
相關標籤/搜索