Apache Thrift學習之一(入門及Java實例演示)


目錄:

  • 概述
  • 下載配置
  • 基本概念
    1. 數據類型
    2. 服務端編碼基本步驟
    3. 客戶端編碼基本步驟
    4. 數據傳輸協議
  • 實例演示(java)
    1.  thrift生成代碼
    2.  實現接口Iface
    3. TSimpleServer服務模型
    4. TThreadPoolServer 服務模型
    5. TNonblockingServer 服務模型
    6. THsHaServer服務模型
    7. 異步客戶端

[一]、概述

Apache Thrift 是 Facebook 實現的一種高效的、支持多種編程語言的遠程服務調用的框架。Thrift是由Facebook開發的,並在2008年捐給了Apache基金會,成為了一個孵化器項目。

Thrift是一個軟件框架,用來進行可擴展且跨語言的服務的開發。它結合了功能強大的軟件堆棧和代碼生成引擎,

Thrift是一個驅動層接口,它提供了用於客戶端使用多種語言實現的API。
Thrift是個代碼生成庫,支持的客戶端語言包括C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 。它的目標是為了各種流行的語言提供便利的RPC調用機制,而不需要使用那些開銷巨大的方式,比如SOAP。

要使用Thrift,就要使用一個語言中立的服務定義文件,描述數據類型和服務接口。這個文件會被用作引擎的輸入,編譯器生成代碼為每種支持的語言生成RPC客戶端代碼庫。這種靜態生成的設計讓它非常容易被開發者所使用,而且因為類型驗證都發生在編譯期而非運行期,所以代碼可以很有效率地運行。

Thrift的設計提供了以下這些特性:
1、語言無關的類型
因為類型是使用定義文件按照語言中立的方式規定的,所以它們可以被不同的語言分析。比如,C++的結構可以和Python的字典類型相互交換數據。
2、通用傳輸接口
不論你使用的是磁盤文件、內存數據還是socket流,都可以使用同一段應用代碼。
3、協議無關
Thrift會對數據類型進行編碼和解碼,可以跨協議使用。
4、支持版本
數據類型可以加入版本信息,來支持客戶端API的更新。

 

官網地址:thrift.apache.org

推薦值得一看的文章:

[二]、下載配置

1)安裝thrift:到thrift官網下載exe文件,然后將文件重命名為thrift.exe,拷貝到D:\EBOOK\thrift目錄下(或者任何目錄下),然后就可以在dos環境下使用了

  D:\EBOOK\thrift>thrift -gen java D:\work\workspace\thriftworkspace\demo1\demoHello.thrift ,輸出的java文件默認輸出到當前目錄下D:\EBOOK\thrift\gen-java,也可以使用-o參數指定輸出路徑;

  2)下載相關依賴包

  2.1)libthrift.jar ,下載地址:http://repo1.maven.org/maven2/org/apache/thrift/libthrift/0.9.0/

  2.2)slf4j-api.jar

  2.3)slf4j-simple.jar

到官網http://thrift.apache.org/download 下載最新版本,截止今日(2016-05-23)最新版本為0.9.3

1. 如果是Maven構建項目的,直接在pom.xml 中添加如下內容:

2.如果自己編譯lib包,把下載的壓縮包解壓到X:盤,然后在X:\thrift-0.8.0\lib\java 目錄下運行ant進行自動編譯,會在X:\thrift-0.8.0\lib\java\build\ 目錄下看到編譯好的lib包:libthrift-0.8.0.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文件:D:\work\workspace\thriftworkspace\demo1\demoHello.thrift ,內容如下:

thrift-0.8.0.exe 是官網提供的windows下編譯工具,運用這個工具生成相關代碼:

生成后的目錄結構如下:

將生成的HelloWorldService.java 文件copy到自己測試的工程中,我的工程是用maven構建的,故在pom.xml中增加如下內容:

2. 實現接口Iface

java代碼:HelloWorldImpl.java

3.TSimpleServer服務端

簡單的單線程服務模型,一般用於測試。

編寫服務端server代碼:HelloServerDemo.java

編寫客戶端Client代碼:HelloClientDemo.java

package com.dxz.thrift.demo;

import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TJSONProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

public class HelloClientDemo {

    public static final String SERVER_IP = "localhost";
    public static final int SERVER_PORT = 8090;
    public static final int TIMEOUT = 30000;

    /**
     *
     * @param userName
     */
    public void startClient(String userName) {
        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);
            HelloWorldService.Client client = new HelloWorldService.Client(protocol);
            transport.open();
            String result = client.sayHello(userName);
            System.out.println("Thrify client result =: " + result);
        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            if (null != transport) {
                transport.close();
            }
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        HelloClientDemo client = new HelloClientDemo();
        client.startClient("china");

    }

}

先運行服務端程序,日志如下:

再運行客戶端調用程序,日志如下:

Thrify client result =: Hi,china welcome to thrift world.

測試成功,和預期的返回信息一致。

 

4.TThreadPoolServer 服務模型

線程池服務模型,使用標准的阻塞式IO,預先創建一組線程處理請求。

編寫服務端代碼:HelloServerDemo2.java

package com.dxz.thrift.demo;

import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TServerSocket;

public class HelloServerDemo2 {
    public static final int SERVER_PORT = 8090;

    public void startServer() {
        try {
            System.out.println("HelloWorld TThreadPoolServer start ....");

            TProcessor tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>(new HelloWorldImpl());

            TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
            TThreadPoolServer.Args ttpsArgs = new TThreadPoolServer.Args(serverTransport);
            ttpsArgs.processor(tprocessor);
            ttpsArgs.protocolFactory(new TBinaryProtocol.Factory());

            // 線程池服務模型,使用標准的阻塞式IO,預先創建一組線程處理請求。
            TServer server = new TThreadPoolServer(ttpsArgs);
            server.serve();

        } catch (Exception e) {
            System.out.println("Server start error!!!");
            e.printStackTrace();
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        HelloServerDemo2 server = new HelloServerDemo2();
        server.startServer();
    }

}

客戶端Client代碼和之前的一樣,只要數據傳輸的協議一致即可,客戶端測試成功,結果如下:

5.TNonblockingServer 服務模型

使用非阻塞式IO,服務端和客戶端需要指定 TFramedTransport 數據傳輸的方式。

編寫服務端代碼:HelloServerDemo3.java

編寫客戶端代碼:HelloClientDemo3.java

package com.dxz.thrift.demo;

import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TJSONProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

public class HelloClientDemo3 {

    public static final String SERVER_IP = "localhost";
    public static final int SERVER_PORT = 8090;
    public static final int TIMEOUT = 30000;

    public void startClient(String userName) {
        TTransport transport = null;
        try {
            transport = new TFramedTransport(new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT));
            // 協議要和服務端一致
            TProtocol protocol = new TCompactProtocol(transport);
            HelloWorldService.Client client = new HelloWorldService.Client(protocol);
            transport.open();
            String result = client.sayHello(userName);
            System.out.println("Thrify client result =: " + result);
        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            if (null != transport) {
                transport.close();
            }
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        HelloClientDemo3 client = new HelloClientDemo3();
        client.startClient("HelloClientDemo3");

    }

}

客戶端的測試成功,結果如下:

Thrify client result =: Hi,HelloClientDemo3 welcome to thrift world.

6.THsHaServer服務模型

半同步半異步的服務端模型,需要指定為: TFramedTransport 數據傳輸的方式。

編寫服務端代碼:HelloServerDemo4.java

package com.dxz.thrift.demo;

import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.TNonblockingServer;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TServerSocket;

public class HelloServerDemo4 {
    public static final int SERVER_PORT = 8090;

    public void startServer() {
        try {
            System.out.println("HelloWorld THsHaServer start ....");

            TProcessor tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>(new HelloWorldImpl());

            TNonblockingServerSocket tnbSocketTransport = new TNonblockingServerSocket(SERVER_PORT);
            THsHaServer.Args thhsArgs = new THsHaServer.Args(tnbSocketTransport);
            thhsArgs.processor(tprocessor);
            thhsArgs.transportFactory(new TFramedTransport.Factory());
            thhsArgs.protocolFactory(new TBinaryProtocol.Factory());

            // 半同步半異步的服務模型
            TServer server = new THsHaServer(thhsArgs);
            server.serve();

        } catch (Exception e) {
            System.out.println("Server start error!!!");
            e.printStackTrace();
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        HelloServerDemo4 server = new HelloServerDemo4();
        server.startServer();
    }

}

客戶端代碼HelloClientDemo4.java

package com.dxz.thrift.demo;

import java.io.IOException;

import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

public class HelloClientDemo4 {

    public static final String SERVER_IP = "localhost";
    public static final int SERVER_PORT = 8090;
    public static final int TIMEOUT = 30000;

    public void startClient(String userName) {
        TTransport transport = null;
        try {
            transport = new TFramedTransport(new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT));
            // 協議要和服務端一致
            TProtocol protocol = new TBinaryProtocol(transport);
            // TProtocol protocol = new TCompactProtocol(transport);
            // TProtocol protocol = new TJSONProtocol(transport);
            HelloWorldService.Client client = new HelloWorldService.Client(protocol);
            transport.open();
            String result = client.sayHello(userName);
            System.out.println("Thrify client result =: " + result);
        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            if (null != transport) {
                transport.close();
            }
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        HelloClientDemo4 client = new HelloClientDemo4();
        client.startClient("HelloClientDemo4");

    }

}

 

結果:Thrify client result =: Hi,HelloClientDemo4 welcome to thrift world.

7.異步客戶端

編寫服務端代碼:HelloServerDemo5.java

編寫客戶端Client代碼:HelloAsynClientDemo.java

先運行服務程序,再運行客戶端程序,測試結果如下:


免責聲明!

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



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