zoukankan      html  css  js  c++  java
  • Thrift 入门教程

    1. 概述  

      thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Go,Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。Thrift允许定义一个简单的定义文件中的数据类型和服务接口,以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。thrift最初由facebook开发用做系统内各语言之间的RPC通信 。2007年由facebook贡献到apache基金 ,08年5月进入apache孵化器 。

    2. thrift 的跨语言特性

      thrift通过一个中间语言IDL(接口定义语言)来定义RPC的数据类型和接口,这些内容写在以.thrift结尾的文件中,然后通过特殊的编译器来生成不同语言的代码,以满足不同需要的开发者,比如java开发者,就可以生成java代码,c++开发者可以生成c++代码,生成的代码中不但包含目标语言的接口定义,方法,数据类型,还包含有RPC协议层和传输层的实现代码。

    3. thrift 的协议栈结构

    thrift是一种c/s的架构体系.在最上层是用户自行实现的业务逻辑代码.第二层是由thrift编译器自动生成的代码,主要用于结构化数据的解析,发送和接收。TServer主要任务是高效的接受客户端请求,并将请求转发给Processor处理。Processor负责对客户端的请求做出响应,包括RPC请求转发,调用参数解析和用户逻辑调用,返回值写回等处理。从TProtocol以下部分是thirft的传输协议和底层I/O通信。TProtocol是用于数据类型解析的,将结构化数据转化为字节流给TTransport进行传输。TTransport是与底层数据传输密切相关的传输层,负责以字节流方式接收和发送消息体,不关注是什么数据类型。底层IO负责实际的数据传输,包括socket、文件和压缩数据流等。

     4. thrift java 实例

    4.1 创建一个服务HelloWorld

    (1)创建文件Hello.thrift,代码如下:
    namespace java org.wavemelody.thrift.demo
    
    service  HelloWorldService {
      string sayHello(1:string username)
    }

    这里定义了一个HelloWorldService 服务,包含一个sayHello方法,入参和返回值都是一个string类型的参数。

    (2)thrift生成代码
    thrift-0.11.0.exe -r -gen java HelloWorldService.thrift
    thrift-0.11.0.exe是官网提供的windows下编译工具,运用这个工具生成相关代码,生成后的目录结构如下:

    thrift-0.11.0.exe
    HelloWorldService.thrift
    gen-java
      |--org
        |--wavemelody
          |--thrift
            |--demo
              |--HelloWorldService.java

    将生成的 HelloWorldService.java 拷贝到自己的工程中,注意包路径。

    (3)实现Iface

     HelloWorldServiceImpl.java

    package org.wavemelody.thrift.demo;
    
    import org.apache.thrift.TException;
    
    /**
     * Created by Andy on 2018/8/14.
     */
    public class HelloWorldServiceImpl implements HelloWorldService.Iface{
        @Override
        public String helloString(String para) throws TException {
            return "Hello " + para;
        }
    }
    (4) 创建TSimpleServer服务端

    创建服务器端实现代码,将 HelloServiceImpl 作为具体的处理器传递给 Thrift 服务器,代码如下:

    HelloServiceServer.java

    package org.wavemelody.thrift.demo;
    
    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;
    import org.apache.thrift.transport.TTransportException;
    
    /**
     * Created by Andy on 2018/8/14.
     */
    public class HelloServiceServer {
        public void startServer(){
            try {
             System.out.println(
    "HelloWorldServer start ... "); TServerSocket serverTransport = new TServerSocket(8888); TServer.Args tArgs = new TServer.Args(serverTransport); TProcessor tProcessor = new HelloWorldService.Processor<HelloWorldService.Iface>(new HelloWorldServiceImpl()); 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 (TTransportException e) { e.printStackTrace(); } } public static void main(String[] args){ HelloServiceServer serviceServer = new HelloServiceServer(); serviceServer.startServer(); } }
    (5)编写客户端Client代码
    HelloServiceClient.java
    package org.wavemelody.thrift.demo;
    
    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 Andy on 2018/8/14.
     */
    public class HelloServiceClient {
        public void startClient(String username){
            TTransport tTransport = null;
            try {
                tTransport = new TSocket("localhost",8888,30000);
                // 协议要和服务端一致
                TProtocol protocol = new TBinaryProtocol(tTransport);
    //            TProtocol protocol = new TCompactProtocol(tTransport);
    //            TProtocol protocol = new TJSONProtocol(tTransport);
                HelloWorldService.Client client = new HelloWorldService.Client(protocol);
                tTransport.open();
                String result = client.helloString(username);
                System.out.println("Thrify client result = " + result);
            } catch (TTransportException ex) {
                ex.printStackTrace();
            } catch (TException ex) {
                ex.printStackTrace();
            }finally {
                if(tTransport != null){
                    tTransport.close();
                }
            }
        }
        public static void main(String[] args){
            HelloServiceClient client = new HelloServiceClient();
            client.startClient(" world");
        }
    }
     (6)测试远程调用

    启动服务端,日志如下:

    启动客户端,日志如下:

    调用成功,符合预期结果。

    4.2 TThreadPoolServer 服务模型

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

    ThreadPoolHelloServiceServer.java

    package org.wavemelody.thrift.demo;
    
    import org.apache.thrift.TProcessor;
    import org.apache.thrift.protocol.TBinaryProtocol;
    import org.apache.thrift.server.TThreadPoolServer;
    import org.apache.thrift.transport.TServerSocket;
    import org.apache.thrift.transport.TTransportException;
    
    /**
     * Created by Andy on 2018/8/14.
     */
    public class ThreadPoolHelloServiceServer {
        public void startServer(){
            try {
                System.out.println("HelloWorldServer start ... ");
                TServerSocket serverTransport = new TServerSocket(8888);
                TThreadPoolServer.Args tArgs = new TThreadPoolServer.Args(serverTransport);
                TProcessor tProcessor = new HelloWorldService.Processor<HelloWorldService.Iface>(new HelloWorldServiceImpl());
                tArgs.processor(tProcessor);
                tArgs.protocolFactory(new TBinaryProtocol.Factory());
                // 线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求。
                TThreadPoolServer server = new TThreadPoolServer(tArgs);
                server.serve();
            } catch (TTransportException e) {
                e.printStackTrace();
            }
        }
        public static void main(String[] args){
            ThreadPoolHelloServiceServer serviceServer = new ThreadPoolHelloServiceServer();
            serviceServer.startServer();
        }
    }

    客户端和之前的代码一样,测试结果如下:

    4.3  TNonblockingServer 服务模型

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

    服务端代码 TNonblockingHelloServiceServer.java

    package org.wavemelody.thrift.demo;
    
    import org.apache.thrift.TMultiplexedProcessor;
    import org.apache.thrift.TProcessor;
    import org.apache.thrift.protocol.TBinaryProtocol;
    import org.apache.thrift.protocol.TCompactProtocol;
    import org.apache.thrift.server.TNonblockingServer;
    import org.apache.thrift.transport.TFramedTransport;
    import org.apache.thrift.transport.TNonblockingServerSocket;
    import org.apache.thrift.transport.TTransportException;
    
    /**
     * Created by Andy on 2018/8/14.
     */
    public class TNonblockingHelloServiceServer {
        public void startServer(){
            try {
                System.out.println("HelloWorldServer start ... ");
                TNonblockingServerSocket tnbSocket = new TNonblockingServerSocket(8888);
                TNonblockingServer.Args tArgs = new TNonblockingServer.Args(tnbSocket);
                TProcessor tProcessor = new HelloWorldService.Processor<HelloWorldService.Iface>(new HelloWorldServiceImpl());
                tArgs.processor(tProcessor);
                tArgs.protocolFactory(new TBinaryProtocol.Factory());
                tArgs.transportFactory(new TFramedTransport.Factory());
                // 线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求。
                TNonblockingServer server = new TNonblockingServer(tArgs);
                server.serve();
            } catch (TTransportException e) {
                e.printStackTrace();
            }
        }
        public static void main(String[] args){
            TNonblockingHelloServiceServer serviceServer = new TNonblockingHelloServiceServer();
            serviceServer.startServer();
        }
    }

    客户端代码:TNonblockingHelloServiceClient.java

    package org.wavemelody.thrift.demo;
    
    import org.apache.thrift.TException;
    import org.apache.thrift.protocol.TBinaryProtocol;
    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;
    
    /**
     * Created by Andy on 2018/8/14.
     */
    public class TNonblockingHelloServiceClient {
        public void startClient(String username){
            TTransport tTransport = null;
            try {
                tTransport = new TFramedTransport(new TSocket("localhost",8888,30000));
                // 协议要和服务端一致
                TProtocol protocol = new TBinaryProtocol(tTransport);
    //            TProtocol protocol = new TCompactProtocol(tTransport);
    //            TProtocol protocol = new TJSONProtocol(tTransport);
                HelloWorldService.Client client = new HelloWorldService.Client(protocol);
                tTransport.open();
                String result = client.helloString(username);
                System.out.println("Thrify client result = " + result);
            } catch (TTransportException ex) {
                ex.printStackTrace();
            } catch (TException ex) {
                ex.printStackTrace();
            }finally {
                if(tTransport != null){
                    tTransport.close();
                }
            }
        }
        public static void main(String[] args){
            TNonblockingHelloServiceClient client = new TNonblockingHelloServiceClient();
            client.startClient(" world");
        }
    }

    测试结果:

  • 相关阅读:
    优化SQL查询:如何写出高性能SQL语句
    提高SQL执行效率的16种方法
    Spring Ioc DI 原理
    java内存泄漏
    转:js闭包
    LeetCode Best Time to Buy and Sell Stock III
    LeetCode Best Time to Buy and Sell Stock with Cooldown
    LeetCode Length of Longest Fibonacci Subsequence
    LeetCode Divisor Game
    LeetCode Sum of Even Numbers After Queries
  • 原文地址:https://www.cnblogs.com/mymelody/p/9474300.html
Copyright © 2011-2022 走看看