Thrift入門及Java實例演示

最近遇到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客戶端和服務器通信的無縫跨編程語言。


官網地址:thrift.apache.org
[二]、下載配置
到官網下載最新版本,目前最新版本爲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.
————


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章