Thrift是個RPC架構,它的目标是為各種流行的開發語言提供便利的RPC調用機制,而不需要使用那些開銷巨大的方式,比如SOAP。
Thrift使用語言中立的服務定義檔案(IDL,接口描述語言),描述資料類型和服務接口。這個檔案會被用作引擎的輸入,編譯器生成代碼為每種支援的語言生成RPC用戶端代碼庫。這種靜态生成的設計讓它非常容易被開發者所使用,而且因為類型驗證都發生在編譯期而非運作期,是以代碼可以很有效率地運作。
Apache Thrift,它采用接口描述語言(IDL)定義并建立服務,支援可擴充的跨語言服務開發,所包含的代碼生成引擎可以在多種語言中,如 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk 等建立高效的、無縫的服務,其傳輸資料采用二進制格式,相對 XML 和 JSON 體積更小,對于高并發、大資料量和多語言的環境更有優勢。
Thrift 服務開發流程,簡單概述如下:
1、定義IDL檔案(xxx.thrift檔案)
2、用xxx.thrift檔案生成Java代碼(服務接口檔案)
3、服務端實作(建立服務):實作服務接口,開啟伺服器
4、用戶端實作(服務消費):引入接口,進行遠端調用。
Thrift 環境
總體感覺,安裝thrift環境,不算簡單,而且很多人不清楚安裝的那些,到底能幹啥?
Mac 安裝thrift可參考:
https://blog.csdn.net/u010827436/article/details/44303897目前感覺,安裝thrift的目的,就是能夠使用thrift 指令,将xxx.thrift檔案生成Java代碼(僅個人簡單的了解);而生成Java代碼有多種方式,安裝thrift對初學者來說,占據學習的一部分事件,不推薦。
下面快速開始一個簡單的Demo,供初學者對thrift有一個直覺的了解。
1、定義一個IDL接口描述檔案
namespace java com.ljheee.thrift
service QueryService{
string query(1:string query)
}
這個IDL接口描述檔案,采用平台中立、語言中立的方式,描述資料類型和服務接口;即RPC調用過程中,調用方與服務提供方之間通信,傳輸的什麼資料結構、調用的哪個服務接口,是需要在這個.thrift檔案中約定清楚的。
具體檔案含義參考:
如果已經安裝了thrift環境,那麼可以直接使用指令
thrift -gen java demoHello.thrift
生成Java代碼的指令,win、Mac下都相同。指令執行後,會生成一個gen-java檔案夾。
如果還沒有安裝thrift,不要緊,我這裡提供一個下載下傳,先快速上手,預覽全觀。(複制裡面全部内容,建立檔案到對QueryService.java)
https://github.com/ljheee/thrift-demo/blob/master/src/main/java/com/ljheee/thrift/service/QueryService.java其實由第1步的QueryService.thrift檔案,大概可以看出,定義了一個Java service,裡面有一個方法query(String query)。可以預測,它大概是要定義一個接口:
public interface QueryService {
public String query(String query) ;
}
事實上,就是這樣。該接口就是服務提供方和服務調用方之間的約定。服務端通過完成接口的具體實作,對外提供服務,用戶端引入該Java接口,進行遠端調用。當然這隻是簡單描述,thrift生成的QueryService接口裡面也有很多它特定的東西,如傳輸協定、序列化方式等。
3、服務端實作(建立服務)
實作服務接口,開啟伺服器。
把第2步生成的Java檔案(QueryService.java),copy到伺服器端工程,注意package不要錯,然後建立類implements QueryService.Iface
package com.ljheee.thrift.service.impl;
import com.ljheee.thrift.service.QueryService;
import org.apache.thrift.TException;
public class QueryServiceImpl implements QueryService.Iface {
@Override
public String query(String query) throws TException {
return "Hello,"+query;
}
}
開啟伺服器,等待用戶端遠端調用
package com.ljheee.thrift;
import com.ljheee.thrift.service.QueryService;
import com.ljheee.thrift.service.impl.QueryServiceImpl;
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;
public class Server {
public static final int SERVER_PORT = 9999;
public static final String SERVER_IP = "localhost";
public static final int TIMEOUT = 30000;
public static void main(String[] args) {
try {
System.out.println("QueryService TSimpleServer start ....");
TProcessor tprocessor = new QueryService.Processor<QueryService.Iface>(new QueryServiceImpl());
// 簡單的單線程服務模型,一般用于測試
TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
TServer.Args tArgs = new TServer.Args(serverTransport);
tArgs.processor(tprocessor);
tArgs.protocolFactory(new TBinaryProtocol.Factory());
// tArgs.protocolFactory(new TCompactProtocol.Factory());
// tArgs.protocolFactory(new TJSONProtocol.Factory());
TServer server = new TSimpleServer(tArgs);
server.serve();
} catch (Exception e) {
System.out.println("Server start error!!!");
e.printStackTrace();
}
}
}
4、用戶端實作(服務消費)
引入生成接口,進行遠端調用。
同樣把第2步生成的Java檔案(QueryService.java),copy到用戶端工程裡面。本系統為示範友善,在同一個工程中放入了server 和Client的類。
package com.ljheee.thrift;
import com.ljheee.thrift.service.QueryService;
import org.apache.thrift.TException;
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 org.apache.thrift.transport.TTransportException;
/**
* Created by lijianhua04 on 2018/7/27.
*/
public class Client {
public static final int SERVER_PORT = 9999;
public static final String SERVER_IP = "localhost";
public static final int TIMEOUT = 30000;
public static void main(String[] args) {
TTransport transport = null;
try {
transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT);
// 協定要和服務端一緻
TProtocol protocol = new TBinaryProtocol(transport);
// TProtocol protocol = new TCompactProtocol(transport);
// TProtocol protocol = new TJSONProtocol(transport);
QueryService.Client client = new QueryService.Client(protocol);
transport.open();
String result = client.query("ljh");
System.out.println("Thrify client result =: " + result);
} catch (TTransportException e) {
e.printStackTrace();
} catch (TException e) {
e.printStackTrace();
} finally {
if (null != transport) {
transport.close();
}
}
}
}
工程結構目錄
image.png
https://github.com/ljheee/thrift-demo