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");
        }
    }

    测试结果:

  • 相关阅读:
    散列
    Studio 3T破解方式
    springboot整合elasticsearch时的版本问题:
    ElasticSearch6.4.1 【Rejecting mapping update to [posts] as the final mapping would have more than 1 type】
    IP地址查询API
    拉姆达表达式 追加 条件判断 Expression<Func<T, bool>>
    类 映射 遍历大全
    jquery load(URL,FUNCTION(){}) 异步加载页面
    LINQ to Entities 不识别方法的解决方案
    当实体类属性超多时候 映射给实体类属性赋值(拉姆达+实体类映射)
  • 原文地址:https://www.cnblogs.com/mymelody/p/9474300.html
Copyright © 2011-2022 走看看