最近遇到Thrift相關的問題,查閱了網上的資料。很快解決了問題,感謝大神的文章。記錄下來,以備以後查閱。
目錄:
概述下載配置
基本概念
數據類型
服務端編碼基本步驟
客戶端編碼基本步驟
數據傳輸協議
實例演示(java)
thrift生成代碼
實現接口Iface
TSimpleServer服務模型
TThreadPoolServer 服務模型
TNonblockingServer 服務模型
THsHaServer服務模型
異步客戶端
[一]、概述
Thrift 是一個軟件框架,用來進行可擴展且跨語言的服務的開發。它結合了功能強大的軟件堆棧和代碼生成引擎,以構建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 等等編程語言間無縫結合的、高效的服務。
Thrift最初由facebook開發,07年四月開放源碼,08年5月進入apache孵化器。thrift允許你定義一個簡單的定義文件中的數據類型和服務接口。以作爲輸入文件,編譯器生成代碼用來方便地生成RPC客戶端和服務器通信的無縫跨編程語言。
[二]、下載配置
到官網下載最新版本,目前最新版本爲0.9.1.
1. 如果是Maven構建項目的,直接在pom.xml 中添加如下內容:
1 <dependency>
2 <groupId>org.apache.thrift</groupId>
3 <artifactId>libthrift</artifactId>
4 <version>0.9.1</version>
5 </dependency>
2.如果自己編譯lib包,把下載的壓縮包解壓到X:盤,然後在X:\thrift-0.9.1\lib\java 目錄下運行ant進行自動編譯,會在X:\thrift-0.9.1\lib\java\build\ 目錄下看到編譯好的lib包:libthrift-0.9.1.jar
[三]、基本概念
1.數據類型
基本類型:
bool:布爾值,true 或 false,對應 Java 的 boolean
byte:8 位有符號整數,對應 Java 的 byte
i16:16 位有符號整數,對應 Java 的 short
i32:32 位有符號整數,對應 Java 的 int
i64:64 位有符號整數,對應 Java 的 long
double:64 位浮點數,對應 Java 的 double
string:utf-8編碼的字符串,對應 Java 的 String
結構體類型:
struct:定義公共的對象,類似於 C 語言中的結構體定義,在 Java 中是一個 JavaBean
容器類型:
list:對應 Java 的 ArrayList
set:對應 Java 的 HashSet
map:對應 Java 的 HashMap
異常類型:
exception:對應 Java 的 Exception
服務類型:
service:對應服務的類
2.服務端編碼基本步驟:
實現服務處理接口impl
創建TProcessor
創建TServerTransport
創建TProtocol
創建TServer
啓動Server
3.客戶端編碼基本步驟:
創建Transport
創建TProtocol
基於TTransport和TProtocol創建 Client
調用Client的相應方法
4.數據傳輸協議
TBinaryProtocol : 二進制格式.
TCompactProtocol : 壓縮格式
TJSONProtocol : JSON格式
TSimpleJSONProtocol : 提供JSON只寫協議, 生成的文件很容易通過腳本語言解析
tips:客戶端和服務端的協議要一致
[四]、實例演示
1. thrift生成代碼
創建Thrift文件:G:\test\thrift\demoHello.thrift ,內容如下:
1 namespace java com.zhaosoft.thrift.demo
3 service HelloWorldService {
4 string sayHello(1:string username)
5 }
目錄結構如下:
G:\test\thrift>tree /F
G:.
demoHello.thrift
demouser.thrift
thrift-0.9.1.exe
沒有子文件夾
thrift-0.9.1.exe 是官網提供的windows下編譯工具,運用這個工具生成相關代碼:
1 thrift-0.9.1.exe -r -gen java ./demoHello.thrift
生成後的目錄結構如下:
G:\test\thrift>tree /F
G:.
│ demoHello.thrift
│ demouser.thrift
│ thrift-0.9.1.exe
│
└─gen-java
└─com
└─zhaosoft
└─thrift
└─demo
HelloWorldService.java
將生成的HelloWorldService.java 文件copy到自己測試的工程中,我的工程是用maven構建的,故在pom.xml中增加如下內容:
1 <dependency>
2 <groupId>org.apache.thrift</groupId>
3 <artifactId>libthrift</artifactId>
4 <version>0.9.1</version>
5 </dependency>
6 <dependency>
7 <groupId>org.slf4j</groupId>
8 <artifactId>slf4j-log4j12</artifactId>
9 <version>1.7.6</version>
10 </dependency>
2. 實現接口Iface
java代碼:HelloWorldImpl.java
1 packagecom.zhaosoft.thrift.demo;
2
3 importorg.apache.thrift.TException;
4
5 /**
6 *
7 *
8 *
9 *
10 */
11 publicclassHelloWorldImplimplementsHelloWorldService.Iface {
12
13 publicHelloWorldImpl() {
14 }
15
16 @Override
17 publicString sayHello(String username)throwsTException {
18 return"Hi,"+ username +" welcome to my blog www.zhaosoft.com";
19 }
20
21 }
3.TSimpleServer服務端
簡單的單線程服務模型,一般用於測試。
編寫服務端server代碼:HelloServerDemo.java
1 packagecom.zhaosoft.thrift.demo;
2
3 importorg.apache.thrift.TProcessor;
4 importorg.apache.thrift.protocol.TBinaryProtocol;
5 importorg.apache.thrift.protocol.TCompactProtocol;
6 importorg.apache.thrift.protocol.TJSONProtocol;
7 importorg.apache.thrift.protocol.TSimpleJSONProtocol;
8 importorg.apache.thrift.server.TServer;
9 importorg.apache.thrift.server.TSimpleServer;
10 importorg.apache.thrift.transport.TServerSocket;
11
12 /**
13 *
14 *
15 *
16 *
17 */
18 publicclassHelloServerDemo {
19 publicstaticfinalintSERVER_PORT =80;
20
21 publicvoidstartServer() {
22 try{
23 System.out.println("HelloWorld TSimpleServer start ....");
24
25 TProcessor tprocessor =newHelloWorldService.Processor<HelloWorldService.Iface>(
26 newHelloWorldImpl());
27 // HelloWorldService.Processor<HelloWorldService.Iface> tprocessor =
28 // new HelloWorldService.Processor<HelloWorldService.Iface>(
29 // new HelloWorldImpl());
30
31 // 簡單的單線程服務模型,一般用於測試
32 TServerSocket serverTransport =newTServerSocket(SERVER_PORT);
33 TServer.Args tArgs =newTServer.Args(serverTransport);
34 tArgs.processor(tprocessor);
35 tArgs.protocolFactory(newTBinaryProtocol.Factory());
36 // tArgs.protocolFactory(new TCompactProtocol.Factory());
37 // tArgs.protocolFactory(new TJSONProtocol.Factory());
38 TServer server =newTSimpleServer(tArgs);
39 server.serve();
40
41 }catch(Exception e) {
42 System.out.println("Server start error!!!");
43 e.printStackTrace();
44 }
45 }
46
47 /**
48 * @param args
49 */
50 publicstaticvoidmain(String[] args) {
51 HelloServerDemo server =newHelloServerDemo();
52 server.startServer();
53 }
54
55 }
編寫客戶端Client代碼:HelloClientDemo.java
1 packagecom.zhaosoft.thrift.demo;
2
3 importorg.apache.thrift.TException;
4 importorg.apache.thrift.protocol.TBinaryProtocol;
5 importorg.apache.thrift.protocol.TCompactProtocol;
6 importorg.apache.thrift.protocol.TJSONProtocol;
7 importorg.apache.thrift.protocol.TProtocol;
8 importorg.apache.thrift.transport.TSocket;
9 importorg.apache.thrift.transport.TTransport;
10 importorg.apache.thrift.transport.TTransportException;
11
12 /**
13 * blog http://www.zhaosoft.com
14 *
15 * @author zxl
16 *
17 */
18 publicclassHelloClientDemo {
19
20 publicstaticfinalString SERVER_IP ="localhost";
21 publicstaticfinalintSERVER_PORT =80;
22 publicstaticfinalintTIMEOUT =30000;
23
24 /**
25 *
26 * @param userName
27 */
28 publicvoidstartClient(String userName) {
29 TTransport transport =null;
30 try{
31 transport =newTSocket(SERVER_IP, SERVER_PORT, TIMEOUT);
32 // 協議要和服務端一致
33 TProtocol protocol =newTBinaryProtocol(transport);
34 // TProtocol protocol = new TCompactProtocol(transport);
35 // TProtocol protocol = new TJSONProtocol(transport);
36 HelloWorldService.Client client =newHelloWorldService.Client(
37 protocol);
38 transport.open();
39 String result = client.sayHello(userName);
40 System.out.println("Thrify client result =: "+ result);
41 }catch(TTransportException e) {
42 e.printStackTrace();
43 }catch(TException e) {
44 e.printStackTrace();
45 }finally{
46 if(null!= transport) {
47 transport.close();
48 }
49 }
50 }
51
52 /**
53 * @param args
54 */
55 publicstaticvoidmain(String[] args) {
56 HelloClientDemo client =newHelloClientDemo();
57 client.startClient("zxl");
58
59 }
60
61 }
先運行服務端程序,日誌如下:
HelloWorld TSimpleServer start ....
再運行客戶端調用程序,日誌如下:
Thrify client result =: Hi,zxl welcome to my blog www.zhaosoft.com
測試成功,和預期的返回信息一致。
4.TThreadPoolServer 服務模型
線程池服務模型,使用標準的阻塞式IO,預先創建一組線程處理請求。
編寫服務端代碼:HelloServerDemo.java
1 packagecom.zhaosoft.thrift.demo;
2
3 importorg.apache.thrift.TProcessor;
4 importorg.apache.thrift.protocol.TBinaryProtocol;
5 importorg.apache.thrift.server.TServer;
6 importorg.apache.thrift.server.TThreadPoolServer;
7 importorg.apache.thrift.transport.TServerSocket;
8
9 /**
10 * blog http://www.zhaosoft.com
11 *
12 * @author zxl
13 *
14 */
15 publicclassHelloServerDemo {
16 publicstaticfinalintSERVER_PORT =80;
17
18 publicvoidstartServer() {
19 try{
20 System.out.println("HelloWorld TThreadPoolServer start ....");
21
22 TProcessor tprocessor =newHelloWorldService.Processor<HelloWorldService.Iface>(
23 newHelloWorldImpl());
24
25 TServerSocket serverTransport =newTServerSocket(SERVER_PORT);
26 TThreadPoolServer.Args ttpsArgs =newTThreadPoolServer.Args(
27 serverTransport);
28 ttpsArgs.processor(tprocessor);
29 ttpsArgs.protocolFactory(newTBinaryProtocol.Factory());
30
31 // 線程池服務模型,使用標準的阻塞式IO,預先創建一組線程處理請求。
32 TServer server =newTThreadPoolServer(ttpsArgs);
33 server.serve();
34
35 }catch(Exception e) {
36 System.out.println("Server start error!!!");
37 e.printStackTrace();
38 }
39 }
40
41 /**
42 * @param args
43 */
44 publicstaticvoidmain(String[] args) {
45 HelloServerDemo server =newHelloServerDemo();
46 server.startServer();
47 }
48
49 }
客戶端Client代碼和之前的一樣,只要數據傳輸的協議一致即可,客戶端測試成功,結果如下:
Thrify client result =: Hi,zxl welcome to my blog www.zhaosoft.com
5.TNonblockingServer 服務模型
使用非阻塞式IO,服務端和客戶端需要指定 TFramedTransport 數據傳輸的方式。
編寫服務端代碼:HelloServerDemo.java
1 packagecom.zhaosoft.thrift.demo;
2
3 importorg.apache.thrift.TProcessor;
4 importorg.apache.thrift.protocol.TCompactProtocol;
5 importorg.apache.thrift.server.TNonblockingServer;
6 importorg.apache.thrift.server.TServer;
7 importorg.apache.thrift.transport.TFramedTransport;
8 importorg.apache.thrift.transport.TNonblockingServerSocket;
9
10 /**
11 * blog http://www.zhaosoft.com
12 *
13 * @author zxl
14 *
15 */
16 publicclassHelloServerDemo {
17 publicstaticfinalintSERVER_PORT =80;
18
19 publicvoidstartServer() {
20 try{
21 System.out.println("HelloWorld TNonblockingServer start ....");
22
23 TProcessor tprocessor =newHelloWorldService.Processor<HelloWorldService.Iface>(
24 newHelloWorldImpl());
25
26 TNonblockingServerSocket tnbSocketTransport =newTNonblockingServerSocket(
27 SERVER_PORT);
28 TNonblockingServer.Args tnbArgs =newTNonblockingServer.Args(
29 tnbSocketTransport);
30 tnbArgs.processor(tprocessor);
31 tnbArgs.transportFactory(newTFramedTransport.Factory());
32 tnbArgs.protocolFactory(newTCompactProtocol.Factory());
33
34 // 使用非阻塞式IO,服務端和客戶端需要指定TFramedTransport數據傳輸的方式
35 TServer server =newTNonblockingServer(tnbArgs);
36 server.serve();
37
38 }catch(Exception e) {
39 System.out.println("Server start error!!!");
40 e.printStackTrace();
41 }
42 }
43
44 /**
45 * @param args
46 */
47 publicstaticvoidmain(String[] args) {
48 HelloServerDemo server =newHelloServerDemo();
49 server.startServer();
50 }
51
52 }
編寫客戶端代碼:HelloClientDemo.java
1 packagecom.zhaosoft.thrift.demo;
2
3 importorg.apache.thrift.TException;
4 importorg.apache.thrift.protocol.TCompactProtocol;
5 importorg.apache.thrift.protocol.TProtocol;
6 importorg.apache.thrift.transport.TFramedTransport;
7 importorg.apache.thrift.transport.TSocket;
8 importorg.apache.thrift.transport.TTransport;
9 importorg.apache.thrift.transport.TTransportException;
10
11 /**
12 * blog http://www.zhaosoft.com
13 *
14 * @author zxl
15 *
16 */
17 publicclassHelloClientDemo {
18
19 publicstaticfinalString SERVER_IP ="localhost";
20 publicstaticfinalintSERVER_PORT =80;
21 publicstaticfinalintTIMEOUT =30000;
22
23 /**
24 *
25 * @param userName
26 */
27 publicvoidstartClient(String userName) {
28 TTransport transport =null;
29 try{
30 transport =newTFramedTransport(newTSocket(SERVER_IP,
31 SERVER_PORT, TIMEOUT));
32 // 協議要和服務端一致
33 TProtocol protocol =newTCompactProtocol(transport);
34 HelloWorldService.Client client =newHelloWorldService.Client(
35 protocol);
36 transport.open();
37 String result = client.sayHello(userName);
38 System.out.println("Thrify client result =: "+ result);
39 }catch(TTransportException e) {
40 e.printStackTrace();
41 }catch(TException e) {
42 e.printStackTrace();
43 }finally{
44 if(null!= transport) {
45 transport.close();
46 }
47 }
48 }
49
50 /**
51 * @param args
52 */
53 publicstaticvoidmain(String[] args) {
54 HelloClientDemo client =newHelloClientDemo();
55 client.startClient("zxl");
56
57 }
58
59 }
客戶端的測試成功,結果如下:
Thrify client result =: Hi,zxl welcome to my blog www.zhaosoft.com
6.THsHaServer服務模型
半同步半異步的服務端模型,需要指定爲: TFramedTransport 數據傳輸的方式。
編寫服務端代碼:HelloServerDemo.java
1 packagecom.zhaosoft.thrift.demo;
2
3 importorg.apache.thrift.TProcessor;
4 importorg.apache.thrift.protocol.TBinaryProtocol;
5 importorg.apache.thrift.protocol.TCompactProtocol;
6 importorg.apache.thrift.server.THsHaServer;
7 importorg.apache.thrift.server.TNonblockingServer;
8 importorg.apache.thrift.server.TServer;
9 importorg.apache.thrift.server.TSimpleServer;
10 importorg.apache.thrift.server.TThreadPoolServer;
11 importorg.apache.thrift.transport.TFramedTransport;
12 importorg.apache.thrift.transport.TNonblockingServerSocket;
13 importorg.apache.thrift.transport.TServerSocket;
14
15 /**
16 * blog http://www.zhaosoft.com
17 *
18 * @author zxl
19 *
20 */
21 publicclassHelloServerDemo {
22 publicstaticfinalintSERVER_PORT =80;
23
24 publicvoidstartServer() {
25 try{
26 System.out.println("HelloWorld THsHaServer start ....");
27
28 TProcessor tprocessor =newHelloWorldService.Processor<HelloWorldService.Iface>(
29 newHelloWorldImpl());
30
31 TNonblockingServerSocket tnbSocketTransport =newTNonblockingServerSocket(
32 SERVER_PORT);
33 THsHaServer.Args thhsArgs =newTHsHaServer.Args(tnbSocketTransport);
34 thhsArgs.processor(tprocessor);
35 thhsArgs.transportFactory(newTFramedTransport.Factory());
36 thhsArgs.protocolFactory(newTBinaryProtocol.Factory());
37
38 //半同步半異步的服務模型
39 TServer server =newTHsHaServer(thhsArgs);
40 server.serve();
41
42 }catch(Exception e) {
43 System.out.println("Server start error!!!");
44 e.printStackTrace();
45 }
46 }
47
48 /**
49 * @param args
50 */
51 publicstaticvoidmain(String[] args) {
52 HelloServerDemo server =newHelloServerDemo();
53 server.startServer();
54 }
55
56 }
客戶端代碼和上面 4 中的類似,只要注意傳輸協議一致以及指定傳輸方式爲TFramedTransport。
7.異步客戶端
編寫服務端代碼:HelloServerDemo.java
1 packagecom.zhaosoft.thrift.demo;
2
3 importorg.apache.thrift.TProcessor;
4 importorg.apache.thrift.protocol.TCompactProtocol;
5 importorg.apache.thrift.server.TNonblockingServer;
6 importorg.apache.thrift.server.TServer;
7 importorg.apache.thrift.transport.TFramedTransport;
8 importorg.apache.thrift.transport.TNonblockingServerSocket;
9
10 /**
11 * blog http://www.zhaosoft.com
12 *
13 * @author zxl
14 *
15 */
16 publicclassHelloServerDemo {
17 publicstaticfinalintSERVER_PORT =80;
18
19 publicvoidstartServer() {
20 try{
21 System.out.println("HelloWorld TNonblockingServer start ....");
22
23 TProcessor tprocessor =newHelloWorldService.Processor<HelloWorldService.Iface>(
24 newHelloWorldImpl());
25
26 TNonblockingServerSocket tnbSocketTransport =newTNonblockingServerSocket(
27 SERVER_PORT);
28 TNonblockingServer.Args tnbArgs =newTNonblockingServer.Args(
29 tnbSocketTransport);
30 tnbArgs.processor(tprocessor);
31 tnbArgs.transportFactory(newTFramedTransport.Factory());
32 tnbArgs.protocolFactory(newTCompactProtocol.Factory());
33
34 // 使用非阻塞式IO,服務端和客戶端需要指定TFramedTransport數據傳輸的方式
35 TServer server =newTNonblockingServer(tnbArgs);
36 server.serve();
37
38 }catch(Exception e) {
39 System.out.println("Server start error!!!");
40 e.printStackTrace();
41 }
42 }
43
44 /**
45 * @param args
46 */
47 publicstaticvoidmain(String[] args) {
48 HelloServerDemo server =newHelloServerDemo();
49 server.startServer();
50 }
51
52 }
編寫客戶端Client代碼:HelloAsynClientDemo.java
1 packagecom.zhaosoft.thrift.demo;
2
3 importjava.util.concurrent.CountDownLatch;
4 importjava.util.concurrent.TimeUnit;
5
6 importorg.apache.thrift.TException;
7 importorg.apache.thrift.async.AsyncMethodCallback;
8 importorg.apache.thrift.async.TAsyncClientManager;
9 importorg.apache.thrift.protocol.TCompactProtocol;
10 importorg.apache.thrift.protocol.TProtocolFactory;
11 importorg.apache.thrift.transport.TNonblockingSocket;
12 importorg.apache.thrift.transport.TNonblockingTransport;
13
14 importcom.zhaosoft.thrift.demo.HelloWorldService.AsyncClient.sayHello_call;
15
16 /**
17 * blog http://www.zhaosoft.com
18 *
19 * @author zxl
20 *
21 */
22 publicclassHelloAsynClientDemo {
23
24 publicstaticfinalString SERVER_IP ="localhost";
25 publicstaticfinalintSERVER_PORT =80;
26 publicstaticfinalintTIMEOUT =30000;
27
28 /**
29 *
30 * @param userName
31 */
32 publicvoidstartClient(String userName) {
33 try{
34 TAsyncClientManager clientManager =newTAsyncClientManager();
35 TNonblockingTransport transport =newTNonblockingSocket(SERVER_IP,
36 SERVER_PORT, TIMEOUT);
37
38 TProtocolFactory tprotocol =newTCompactProtocol.Factory();
39 HelloWorldService.AsyncClient asyncClient =newHelloWorldService.AsyncClient(
40 tprotocol, clientManager, transport);
41 System.out.println("Client start .....");
42
43 CountDownLatch latch =newCountDownLatch(1);
44 AsynCallback callBack =newAsynCallback(latch);
45 System.out.println("call method sayHello start ...");
46 asyncClient.sayHello(userName, callBack);
47 System.out.println("call method sayHello .... end");
48 booleanwait = latch.await(30, TimeUnit.SECONDS);
49 System.out.println("latch.await =:"+ wait);
50 }catch(Exception e) {
51 e.printStackTrace();
52 }
53 System.out.println("startClient end.");
54 }
55
56 publicclassAsynCallbackimplementsAsyncMethodCallback<sayHello_call> {
57 privateCountDownLatch latch;
58
59 publicAsynCallback(CountDownLatch latch) {
60 this.latch = latch;
61 }
62
63 @Override
64 publicvoidonComplete(sayHello_call response) {
65 System.out.println("onComplete");
66 try{
67 // Thread.sleep(1000L * 1);
68 System.out.println("AsynCall result =:"
69 + response.getResult().toString());
70 }catch(TException e) {
71 e.printStackTrace();
72 }catch(Exception e) {
73 e.printStackTrace();
74 }finally{
75 latch.countDown();
76 }
77 }
78
79 @Override
80 publicvoidonError(Exception exception) {
81 System.out.println("onError :"+ exception.getMessage());
82 latch.countDown();
83 }
84 }
85
86 /**
87 * @param args
88 */
89 publicstaticvoidmain(String[] args) {
90 HelloAsynClientDemo client =newHelloAsynClientDemo();
91 client.startClient("zxl");
92
93 }
94
95 }
先運行服務程序,再運行客戶端程序,測試結果如下:
Client start .....
call method sayHello start ...
call method sayHello .... end
onComplete
AsynCall result =:Hi,zxl welcome to my blog www.zhaosoft.com
latch.await =:true
startClient end.
————