• Thrift入门及Java实例演示 | micmiu 大大的技术 | 小小的生活


    Thrift入门及Java实例演示 | micmiu - 大大的技术 | 小小的生活

    Thrift入门及Java实例演示

    目录:

    • 概述
    • 下载配置
    • 基本概念
      1. 数据类型
      2. 服务端编码基本步骤
      3. 客户端编码基本步骤
      4. 数据传输协议
    • 实例演示(java)
      1.  thrift生成代码
      2.  实现接口Iface
      3. TSimpleServer服务模型
      4. TThreadPoolServer 服务模型
      5. TNonblockingServer 服务模型
      6. THsHaServer服务模型
      7. 异步客户端

    [一]、概述

    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

    推荐值得一看的文章:

    [二]、下载配置

    到官网下载最新版本,截止今日(2012-06-11)最新版本为0.8.0.

    1. 如果是Maven构建项目的,直接在pom.xml 中添加如下内容:

    1<dependency>
    2  <groupId>org.apache.thrift</groupId>
    3  <artifactId>libthrift</artifactId>
    4  <version>0.8.0</version>
    5</dependency>

    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文件:G:\test\thrift\demoHello.thrift ,内容如下:

    1namespace java com.micmiu.thrift.demo
    2 
    3service  HelloWorldService {
    4  string sayHello(1:string username)
    5}

    目录结构如下:

    G:\test\thrift>tree /F
    卷 other 的文件夹 PATH 列表
    卷序列号为 D238-BE47
    G:.
        demoHello.thrift
        demouser.thrift
        thrift-0.8.0.exe
    
    没有子文件夹

    thrift-0.8.0.exe 是官网提供的windows下编译工具,运用这个工具生成相关代码:

    1thrift-0.8.0.exe -r -gen java ./demoHello.thrift

    生成后的目录结构如下:

    G:\test\thrift>tree /F
    卷 other 的文件夹 PATH 列表
    卷序列号为 D238-BE47
    G:.
    │  demoHello.thrift
    │  demouser.thrift
    │  thrift-0.8.0.exe
    │
    └─gen-java
        └─com
            └─micmiu
                └─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.8.0</version>
    5</dependency>
    6<dependency>
    7    <groupId>org.slf4j</groupId>
    8    <artifactId>slf4j-log4j12</artifactId>
    9    <version>1.5.8</version>
    10</dependency>

    2. 实现接口Iface

    java代码:HelloWorldImpl.java

    1package com.micmiu.thrift.demo;
    2 
    3import org.apache.thrift.TException;
    4 
    5/**
    7 *
    8 * @author Michael
    9 *
    10 */
    11public class HelloWorldImpl implements HelloWorldService.Iface {
    12 
    13    public HelloWorldImpl() {
    14    }
    15 
    16    @Override
    17    public String sayHello(String username) throws TException {
    18        return "Hi," + username + " welcome to my blog www.micmiu.com";
    19    }
    20 
    21}

    3.TSimpleServer服务端

    简单的单线程服务模型,一般用于测试。

    编写服务端server代码:HelloServerDemo.java

    1package com.micmiu.thrift.demo;
    2 
    3import org.apache.thrift.TProcessor;
    4import org.apache.thrift.protocol.TBinaryProtocol;
    5import org.apache.thrift.protocol.TCompactProtocol;
    6import org.apache.thrift.protocol.TJSONProtocol;
    7import org.apache.thrift.protocol.TSimpleJSONProtocol;
    8import org.apache.thrift.server.TServer;
    9import org.apache.thrift.server.TSimpleServer;
    10import org.apache.thrift.transport.TServerSocket;
    11 
    12/**
    14 *
    15 * @author Michael
    16 *
    17 */
    18public class HelloServerDemo {
    19    public static final int SERVER_PORT = 8090;
    20 
    21    public void startServer() {
    22        try {
    23            System.out.println("HelloWorld TSimpleServer start ....");
    24 
    25            TProcessor tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>(
    26                    new HelloWorldImpl());
    27            // HelloWorldService.Processor<HelloWorldService.Iface> tprocessor =
    28            // new HelloWorldService.Processor<HelloWorldService.Iface>(
    29            // new HelloWorldImpl());
    30 
    31            // 简单的单线程服务模型,一般用于测试
    32            TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
    33            TServer.Args tArgs = new TServer.Args(serverTransport);
    34            tArgs.processor(tprocessor);
    35            tArgs.protocolFactory(new TBinaryProtocol.Factory());
    36            // tArgs.protocolFactory(new TCompactProtocol.Factory());
    37            // tArgs.protocolFactory(new TJSONProtocol.Factory());
    38            TServer server = new TSimpleServer(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    public static void main(String[] args) {
    51        HelloServerDemo server = new HelloServerDemo();
    52        server.startServer();
    53    }
    54 
    55}

    编写客户端Client代码:HelloClientDemo.java

    1package com.micmiu.thrift.demo;
    2 
    3import org.apache.thrift.TException;
    4import org.apache.thrift.protocol.TBinaryProtocol;
    5import org.apache.thrift.protocol.TCompactProtocol;
    6import org.apache.thrift.protocol.TJSONProtocol;
    7import org.apache.thrift.protocol.TProtocol;
    8import org.apache.thrift.transport.TSocket;
    9import org.apache.thrift.transport.TTransport;
    10import org.apache.thrift.transport.TTransportException;
    11 
    12/**
    14 *
    15 * @author Michael
    16 *
    17 */
    18public class HelloClientDemo {
    19 
    20    public static final String SERVER_IP = "localhost";
    21    public static final int SERVER_PORT = 8090;
    22    public static final int TIMEOUT = 30000;
    23 
    24    /**
    25     *
    26     * @param userName
    27     */
    28    public void startClient(String userName) {
    29        TTransport transport = null;
    30        try {
    31            transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT);
    32            // 协议要和服务端一致
    33            TProtocol protocol = new TBinaryProtocol(transport);
    34            // TProtocol protocol = new TCompactProtocol(transport);
    35            // TProtocol protocol = new TJSONProtocol(transport);
    36            HelloWorldService.Client client = new HelloWorldService.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    public static void main(String[] args) {
    56        HelloClientDemo client = new HelloClientDemo();
    57        client.startClient("Michael");
    58 
    59    }
    60 
    61}

    先运行服务端程序,日志如下:

    HelloWorld TSimpleServer start ....

    再运行客户端调用程序,日志如下:

    Thrify client result =: Hi,Michael welcome to my blog www.micmiu.com

    测试成功,和预期的返回信息一致。

    4.TThreadPoolServer 服务模型

    线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求。

    编写服务端代码:HelloServerDemo.java

    1package com.micmiu.thrift.demo;
    2 
    3import org.apache.thrift.TProcessor;
    4import org.apache.thrift.protocol.TBinaryProtocol;
    5import org.apache.thrift.server.TServer;
    6import org.apache.thrift.server.TThreadPoolServer;
    7import org.apache.thrift.transport.TServerSocket;
    8 
    9/**
    11 *
    12 * @author Michael
    13 *
    14 */
    15public class HelloServerDemo {
    16    public static final int SERVER_PORT = 8090;
    17 
    18    public void startServer() {
    19        try {
    20            System.out.println("HelloWorld TThreadPoolServer start ....");
    21 
    22            TProcessor tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>(
    23                    new HelloWorldImpl());
    24 
    25             TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
    26             TThreadPoolServer.Args ttpsArgs = new TThreadPoolServer.Args(
    27             serverTransport);
    28             ttpsArgs.processor(tprocessor);
    29             ttpsArgs.protocolFactory(new TBinaryProtocol.Factory());
    30 
    31            // 线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求。
    32             TServer server = new TThreadPoolServer(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    public static void main(String[] args) {
    45        HelloServerDemo server = new HelloServerDemo();
    46        server.startServer();
    47    }
    48 
    49}

    客户端Client代码和之前的一样,只要数据传输的协议一致即可,客户端测试成功,结果如下:

    Thrify client result =: Hi,Michael welcome to my blog www.micmiu.com

    5.TNonblockingServer 服务模型

    使用非阻塞式IO,服务端和客户端需要指定 TFramedTransport 数据传输的方式。

    编写服务端代码:HelloServerDemo.java

    1package com.micmiu.thrift.demo;
    2 
    3import org.apache.thrift.TProcessor;
    4import org.apache.thrift.protocol.TCompactProtocol;
    5import org.apache.thrift.server.TNonblockingServer;
    6import org.apache.thrift.server.TServer;
    7import org.apache.thrift.transport.TFramedTransport;
    8import org.apache.thrift.transport.TNonblockingServerSocket;
    9 
    10/**
    12 *
    13 * @author Michael
    14 *
    15 */
    16public class HelloServerDemo {
    17    public static final int SERVER_PORT = 8090;
    18 
    19    public void startServer() {
    20        try {
    21            System.out.println("HelloWorld TNonblockingServer start ....");
    22 
    23            TProcessor tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>(
    24                    new HelloWorldImpl());
    25 
    26            TNonblockingServerSocket tnbSocketTransport = new TNonblockingServerSocket(
    27                    SERVER_PORT);
    28            TNonblockingServer.Args tnbArgs = new TNonblockingServer.Args(
    29                    tnbSocketTransport);
    30            tnbArgs.processor(tprocessor);
    31            tnbArgs.transportFactory(new TFramedTransport.Factory());
    32            tnbArgs.protocolFactory(new TCompactProtocol.Factory());
    33 
    34            // 使用非阻塞式IO,服务端和客户端需要指定TFramedTransport数据传输的方式
    35            TServer server = new TNonblockingServer(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    public static void main(String[] args) {
    48        HelloServerDemo server = new HelloServerDemo();
    49        server.startServer();
    50    }
    51 
    52}

    编写客户端代码:HelloClientDemo.java

    1package com.micmiu.thrift.demo;
    2 
    3import org.apache.thrift.TException;
    4import org.apache.thrift.protocol.TCompactProtocol;
    5import org.apache.thrift.protocol.TProtocol;
    6import org.apache.thrift.transport.TFramedTransport;
    7import org.apache.thrift.transport.TSocket;
    8import org.apache.thrift.transport.TTransport;
    9import org.apache.thrift.transport.TTransportException;
    10 
    11/**
    13 *
    14 * @author Michael
    15 *
    16 */
    17public class HelloClientDemo {
    18 
    19    public static final String SERVER_IP = "localhost";
    20    public static final int SERVER_PORT = 8090;
    21    public static final int TIMEOUT = 30000;
    22 
    23    /**
    24     *
    25     * @param userName
    26     */
    27    public void startClient(String userName) {
    28        TTransport transport = null;
    29        try {
    30            transport = new TFramedTransport(new TSocket(SERVER_IP,
    31                    SERVER_PORT, TIMEOUT));
    32            // 协议要和服务端一致
    33            TProtocol protocol = new TCompactProtocol(transport);
    34            HelloWorldService.Client client = new HelloWorldService.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    public static void main(String[] args) {
    54        HelloClientDemo client = new HelloClientDemo();
    55        client.startClient("Michael");
    56 
    57    }
    58 
    59}

    客户端的测试成功,结果如下:

    Thrify client result =: Hi,Michael welcome to my blog www.micmiu.com

    6.THsHaServer服务模型

    半同步半异步的服务端模型,需要指定为: TFramedTransport 数据传输的方式。

    编写服务端代码:HelloServerDemo.java

    1package com.micmiu.thrift.demo;
    2 
    3import org.apache.thrift.TProcessor;
    4import org.apache.thrift.protocol.TBinaryProtocol;
    5import org.apache.thrift.protocol.TCompactProtocol;
    6import org.apache.thrift.server.THsHaServer;
    7import org.apache.thrift.server.TNonblockingServer;
    8import org.apache.thrift.server.TServer;
    9import org.apache.thrift.server.TSimpleServer;
    10import org.apache.thrift.server.TThreadPoolServer;
    11import org.apache.thrift.transport.TFramedTransport;
    12import org.apache.thrift.transport.TNonblockingServerSocket;
    13import org.apache.thrift.transport.TServerSocket;
    14 
    15/**
    17 *
    18 * @author Michael
    19 *
    20 */
    21public class HelloServerDemo {
    22    public static final int SERVER_PORT = 8090;
    23 
    24    public void startServer() {
    25        try {
    26            System.out.println("HelloWorld THsHaServer start ....");
    27 
    28            TProcessor tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>(
    29                    new HelloWorldImpl());
    30 
    31            TNonblockingServerSocket tnbSocketTransport = new TNonblockingServerSocket(
    32                    SERVER_PORT);
    33            THsHaServer.Args thhsArgs = new THsHaServer.Args(tnbSocketTransport);
    34            thhsArgs.processor(tprocessor);
    35            thhsArgs.transportFactory(new TFramedTransport.Factory());
    36            thhsArgs.protocolFactory(new TBinaryProtocol.Factory());
    37 
    38            //半同步半异步的服务模型
    39            TServer server = new THsHaServer(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    public static void main(String[] args) {
    52        HelloServerDemo server = new HelloServerDemo();
    53        server.startServer();
    54    }
    55 
    56}

    客户端代码和上面 4 中的类似,只要注意传输协议一致以及指定传输方式为TFramedTransport

    7.异步客户端

    编写服务端代码:HelloServerDemo.java

    1package com.micmiu.thrift.demo;
    2 
    3import org.apache.thrift.TProcessor;
    4import org.apache.thrift.protocol.TCompactProtocol;
    5import org.apache.thrift.server.TNonblockingServer;
    6import org.apache.thrift.server.TServer;
    7import org.apache.thrift.transport.TFramedTransport;
    8import org.apache.thrift.transport.TNonblockingServerSocket;
    9 
    10/**
    12 *
    13 * @author Michael
    14 *
    15 */
    16public class HelloServerDemo {
    17    public static final int SERVER_PORT = 8090;
    18 
    19    public void startServer() {
    20        try {
    21            System.out.println("HelloWorld TNonblockingServer start ....");
    22 
    23            TProcessor tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>(
    24                    new HelloWorldImpl());
    25 
    26            TNonblockingServerSocket tnbSocketTransport = new TNonblockingServerSocket(
    27                    SERVER_PORT);
    28            TNonblockingServer.Args tnbArgs = new TNonblockingServer.Args(
    29                    tnbSocketTransport);
    30            tnbArgs.processor(tprocessor);
    31            tnbArgs.transportFactory(new TFramedTransport.Factory());
    32            tnbArgs.protocolFactory(new TCompactProtocol.Factory());
    33 
    34            // 使用非阻塞式IO,服务端和客户端需要指定TFramedTransport数据传输的方式
    35            TServer server = new TNonblockingServer(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    public static void main(String[] args) {
    48        HelloServerDemo server = new HelloServerDemo();
    49        server.startServer();
    50    }
    51 
    52}

    编写客户端Client代码:HelloAsynClientDemo.java

    1package com.micmiu.thrift.demo;
    2 
    3import java.util.concurrent.CountDownLatch;
    4import java.util.concurrent.TimeUnit;
    5 
    6import org.apache.thrift.TException;
    7import org.apache.thrift.async.AsyncMethodCallback;
    8import org.apache.thrift.async.TAsyncClientManager;
    9import org.apache.thrift.protocol.TCompactProtocol;
    10import org.apache.thrift.protocol.TProtocolFactory;
    11import org.apache.thrift.transport.TNonblockingSocket;
    12import org.apache.thrift.transport.TNonblockingTransport;
    13 
    14import com.micmiu.thrift.demo.HelloWorldService.AsyncClient.sayHello_call;
    15 
    16/**
    18 *
    19 * @author Michael
    20 *
    21 */
    22public class HelloAsynClientDemo {
    23 
    24    public static final String SERVER_IP = "localhost";
    25    public static final int SERVER_PORT = 8090;
    26    public static final int TIMEOUT = 30000;
    27 
    28    /**
    29     *
    30     * @param userName
    31     */
    32    public void startClient(String userName) {
    33        try {
    34            TAsyncClientManager clientManager = new TAsyncClientManager();
    35            TNonblockingTransport transport = new TNonblockingSocket(SERVER_IP,
    36                    SERVER_PORT, TIMEOUT);
    37 
    38            TProtocolFactory tprotocol = new TCompactProtocol.Factory();
    39            HelloWorldService.AsyncClient asyncClient = new HelloWorldService.AsyncClient(
    40                    tprotocol, clientManager, transport);
    41            System.out.println("Client start .....");
    42 
    43            CountDownLatch latch = new CountDownLatch(1);
    44            AsynCallback callBack = new AsynCallback(latch);
    45            System.out.println("call method sayHello start ...");
    46            asyncClient.sayHello(userName, callBack);
    47            System.out.println("call method sayHello .... end");
    48            boolean wait = 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    public class AsynCallback implements AsyncMethodCallback<sayHello_call> {
    57        private CountDownLatch latch;
    58 
    59        public AsynCallback(CountDownLatch latch) {
    60            this.latch = latch;
    61        }
    62 
    63        @Override
    64        public void onComplete(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        public void onError(Exception exception) {
    81            System.out.println("onError :" + exception.getMessage());
    82            latch.countDown();
    83        }
    84    }
    85 
    86    /**
    87     * @param args
    88     */
    89    public static void main(String[] args) {
    90        HelloAsynClientDemo client = new HelloAsynClientDemo();
    91        client.startClient("Michael");
    92 
    93    }
    94 
    95}

    先运行服务程序,再运行客户端程序,测试结果如下:

    Client start .....
    call method sayHello start ...
    call method sayHello .... end
    onComplete
    AsynCall result =:Hi,Michael welcome to my blog www.micmiu.com
    latch.await =:true
    startClient end.

    ————

  • 相关阅读:
    C语言实现—学生成绩管理系统
    C++ 制作一个“测运”小游戏-rand()函数的应用
    C语言实现-航空订票系统(飞机订票系统)
    测试随笔功能
    ASP.Net 连接多个数据库之间的切换
    190906mysql常用语法
    190327 Python登录接口
    190221 百元百鸡
    181102 Windows下安装kivy(用python写APP)
    181102 Python环境搭建(安装Sublime Text3)
  • 原文地址:https://www.cnblogs.com/lexus/p/2920788.html
Copyright © 2020-2023  润新知