Thrift

作者: 不知名的蛋挞 | 来源:发表于2018-11-17 19:49 被阅读1次

    什么是Thrift?

    简单来说,是Facebook公布的一款开源跨语言的RPC框架。

    【什么是RPC框架?】

    RPC全称为Remote Procedure Call,意为远程过程调用。

    假设有两台服务器A,B.A服务器上部署着一个应用a,B服务器上部署着一个应用b,现在a希望能够调用b应用的某个函数(方法),但是二者不在同一个进程内,不能直接调用,就需要通过网络传输,在AB服务器之间建一条网络传输通道,a把参数传过去,b接收到参数调用自己的方法得到结果,再通过网络传回给a。

    简单讲就是A通过网络来调用B的过程,这个过程要涉及的东西很多,比如多线程、Socket、序列化反序列化、网络I/O,很复杂。于是牛掰的程序员把这些封装起来做成一套框架供大家使用,就是RPC框架。

    【Thrift的跨语言特型】

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

    【Thrift的协议栈结构】

    Thrift是一种c/s的架构体系。TServer主要任务是高效的接受客户端请求,并将请求转发给Processor处理。

    • 最上层是用户自行实现的业务逻辑代码;
    • Processor是由thrift编译器自动生成的代码,它封装了从输入数据流中读数据和向数据流中写数据的操作,它的主要工作是:从连接中读取数据,把处理交给用户实现impl,最后把结果写到连接上。
    • TProtocol是用于数据类型解析的,将结构化数据转化为字节流给TTransport进行传输。从TProtocol以下部分是thirft的传输协议和底层I/O通信。
    • TTransport是与底层数据传输密切相关的传输层,负责以字节流方式接收和发送消息体,不关注是什么数据类型。
    • 底层IO负责实际的数据传输,包括socket、文件和压缩数据流等。

    进入Thrift大门的第一个java小实例

    1. 创建一个服务Hello,创建文件Hello.thrift,代码如下:
    namespace java service.demo
    service Hello{
        string helloString(1:string para)
    }
    
    1. 终端进入Hello.thrift所在目录,执行命令:
    thrift -r -gen java Hello.thrift
    

    发现在当前目录下多了一个gen-java的目录,里面的有一个Hello.java的文件。这个java文件包含Hello服务的接口定义Hello.Iface,以及服务调用的底层通信细节,包括客户端的调用逻辑Hello.Client以及服务端的处理逻辑Hello.Processor

    1. 创建一个Maven管理的Java项目,pom.xml中添加相关的依赖,并将Hello.java文件复制到项目中:
    <dependency>
          <groupId>org.apache.thrift</groupId>
          <artifactId>libthrift</artifactId>
          <version>0.10.0</version>
    </dependency>
    <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>1.7.5</version>
    </dependency>
    
    1. 创建HelloServiceImpl实现Hello.Iface接口:
    package service.demo;
    import org.apache.thrift.TException;
    
    public class HelloServiceImpl implements Hello.Iface {
        public String helloString(String para) throws TException {
            return "result:"+para;
        }
    }
    
    1. 创建服务端实现代码HelloServiceServer,把HelloServiceImpl作为一个具体的处理器传递给Thrift服务器:
    public class HelloServiceServer {
        /**
         * 启动thrift服务器
         */
        public static void main(String[] args) {
            try {
                System.out.println("服务端开启....");
                // 1.创建TProcessor
                TProcessor tprocessor = new Hello.Processor<Hello.Iface>(new HelloServiceImpl());
                // 2.创建TserverTransport
                TServerSocket serverTransport = new TServerSocket(9898);
                // 3.创建TProtocol
                TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory();
    
                TServer.Args tArgs = new TServer.Args(serverTransport);
                tArgs.processor(tprocessor);
                tArgs.protocolFactory(factory);
    
                // 4.创建Tserver,传入需要的参数,server将以上内容集成在一起
                TServer server = new TSimpleServer(tArgs);
                // 5.启动server
                server.serve();
            }catch (TTransportException e) {
                e.printStackTrace();
            }
        }
    }
    
    1. 创建客户端实现代码HelloServiceClient,调用Hello.client访问服务端的逻辑实现:
    public class HelloServiceClient {
    
        public static void main(String[] args) {
            System.out.println("客户端启动....");
            TTransport transport = null;
            try {
                transport = new TSocket("localhost", 9898, 30000);
                // 协议要和服务端一致
                TProtocol protocol = new TBinaryProtocol(transport);
                Hello.Client client = new Hello.Client(protocol);
                transport.open();
                String result = client.helloString("哈哈");
                System.out.println(result);
            } catch (TTransportException e) {
                e.printStackTrace();
            } catch (TException e) {
                e.printStackTrace();
            } finally {
                if (null != transport) {
                    transport.close();
                }
            }
        }
    }
    

    全部工作完成后,下面来测试一下,先执行服务端main方法,在执行客户端main方法,会在客户端控制台打印出:哈哈

    相关文章

      网友评论

        本文标题:Thrift

        本文链接:https://www.haomeiwen.com/subject/zirmfqtx.html