Thrift

1,115 阅读3分钟

introduction

The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages.

Thrift是一个轻量级、跨语言的远程服务调用框架,最初由Facebook开发,后面进入Apache开源项目。它通过自身的IDL中间语言, 并借助代码生成引擎生成各种主流语言的RPC服务端/客户端模板代码。

Thrift支持多种不同的编程语言,包括C++、Java、Python、PHP、Ruby等,本系列主要讲述基于Java语言的Thrift的配置方式和具体使用。

quick start

写hello.thrift的IDL文件

service HelloWorldService {
  string say(1: string username)
}

使用代码生成工具生成代码,执行以下命令

thrift -gen java hello.thrift

由于未指定代码生成的目标目录,生成的类文件默认存放在gen-java目录下生成一个HelloWorldService.java类文件

Thrift框架,仅需要关注以下四个核心内部接口/类:Iface, AsyncIface, Client和AsyncClient。

  • Iface:服务端通过实现HelloWorldService.Iface接口,向客户端的提供具体的同步业务逻辑。

  • AsyncIface:服务端通过实现HelloWorldService.Iface接口,向客户端的提供具体的异步业务逻辑。

  • Client:客户端通过HelloWorldService.Client的实例对象,以同步的方式访问服务端提供的服务方法。

  • AsyncClient:客户端通过HelloWorldService.AsyncClient的实例对象,以异步的方式访问服务端提供的服务方法。

public class HelloWorldService {
    public interface Iface {
        public String say(String username) throws org.apache.thrift.TException;
    }

    public interface AsyncIface {
        public void say(String username, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws org.apache.thrift.TException;
    }

    public static class Client extends org.apache.thrift.TServiceClient implements Iface {
        public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
            public Factory() {
            }

            public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
                return new Client(prot);
            }

            public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
                return new Client(iprot, oprot);
            }
        }

        public Client(org.apache.thrift.protocol.TProtocol prot) {
            super(prot, prot);
        }

        public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
            super(iprot, oprot);
        }

        public String say(String username) throws org.apache.thrift.TException {
            send_say(username);
            return recv_say();
        }
        // 省略.....
    }

    public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {
        public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {
            private org.apache.thrift.async.TAsyncClientManager clientManager;
            private org.apache.thrift.protocol.TProtocolFactory protocolFactory;

            public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {
                this.clientManager = clientManager;
                this.protocolFactory = protocolFactory;
            }

            public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {
                return new AsyncClient(protocolFactory, clientManager, transport);
            }
        }

        public AsyncClient(org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.transport.TNonblockingTransport transport) {
            super(protocolFactory, clientManager, transport);
        }

        public void say(String username, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws org.apache.thrift.TException {
            checkReady();
            say_call method_call = new say_call(username, resultHandler, this, ___protocolFactory, ___transport);
            this.___currentMethod = method_call;
            ___manager.call(method_call);
        }
        // 省略.....
    }
    // 省略.....
}

theory

  1. transport

封装socket通信API client端为TTransport server端为TServerTransport

实现种类: TSocket/TServerSocket:使用阻塞式I/O进行传输,是最常见的模式 TFramedTransport/TNonblockingServerTransport:使用非阻塞方式,按块的大小进行传输,类似于Java中的NIO

  1. protocol

指定消息传递格式 client端为TProtocol,持有transport对象,封装按照消息传递指定格式进行读写socket流 server端TProtocolFactory,指定协议类型

  1. Iface/processor/Client

定义rpc接口与接口实现 client端Client实现Iface接口,并且持有protocol对象可以进行消息发送接收,因为Client是thrift自动生成,所以用户可以直接使用 server端processor持有Iface接口实现,封装通用的处理消息逻辑,按照用户指定的protocol读取消息,回调实现的Iface接口方法,返回指定消息格式应答

  1. server

持有transport和processor对象,指定protocolFactory,可以统一thrift服务模型

仅server端,实现种类: TSimpleServer:单线程服务器端,使用标准的阻塞式I/O TThreadPoolServer:多线程服务器端,使用标准的阻塞式I/O

TNonblockingServer:单线程服务器端,使用非阻塞式I/O THsHaServer:半同步半异步服务器端,基于非阻塞式IO读写和多线程工作任务处理 TThreadedSelectorServer:多线程选择器服务器端,对THsHaServer在异步IO模型上进行增强

document

官方文档 Apache Thrift系列讲解博客