定义服务 Thrifty 提供了一套快速发布服务的编程抽象。使用其所定义的 IDL 编写 .thrift ,通过编译生成目标语言的运行代码。其主要的核心是生成 TProcessor 的子类,以及提供一个 IFace 接口。
所以定义服务,其实使用 Thrift IDL 编写 .thrift,然后使用工具生成目标语言的代码。
Thrift 发布服务 对于发布服务方来说,所要做的就是:
实现 IFace 接口,完成服务的功能。
依据业务场景,并发,服务的吞吐量,从 Thtift 提供的 TServer 中选择合适的 Server,启动 Server,从而发布服务。
Thrift 已经提供了多种 Server 模型,不同的 Server 适用于 不同的场景,首先需要根据具体的业务场景选择合适的 Server, Server 的选择关系到,服务运行起来之后的,并发量和吞吐量等,所以需要具体分析,具体选择,最终实现,既可以完成业务功能,又不至于浪费系统资源(主要是 socket 和 线程资源)
关于 Thrift 已经提供的多个 Server 的比较,可以参考:Thrift Java Servers Compared
如果 Thrift 提供的 Server 不能满足需求,可以通过继承 TServer 的方式,实现自己的 Server。
1 2 3 4 5 6 7 8 9 10 11 12 13 TServer _server = new THsHaServer(server_args); _server.serve();
Thrift 使用服务 发布服务生成源码的时候也会生成对应的客户端。
public static class Client extends org.apache.thrift.TServiceClient implements Iface{...}
选择适当的数据传输协议 TProtocol,就可以创建一个客户端。使用这个客户端,连接到服务。就可以像使用本地方法一样,使用远程服务。
Thrift 框架将参数的打包,网络传输,服务端的解析,等过程全部封装好了。有使用 Client 和实现 IFace 的时候都不需要关注这些,只需要实现核心业务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 TSocket socket = new TSocket(_host, _port); TTransport _transport = new TFramedTransport(socket, maxBufferSize); TProtocol _protocol = new TBinaryProtocol(_transport); Nimbus.Client _client = new Nimbus.Client(_protocol); _client.submitTopology();
Thrif 架构设计 功能分层 分层的设计,将复杂的功能,通过抽象以接口和抽象类的形式表达。各层之间的依赖通过,对象组合的方法完成,最终完成整个功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 TTransport client_ = serverTransport_.accept(); processor = processorFactory_.getProcessor(client_); inputTransport = inputTransportFactory_.getTransport(client_); outputTransport = outputTransportFactory_.getTransport(client_); inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); outputProtocol = outputProtocolFactory_.getProtocol(outputTransport);
设计模式的使用 — 工厂方法 org.apache.thrift.server.TServer 及其子类的设计抽象,非常具有代表性。其 serve 方法的实现,也非常值得学习。
设计模式的使用通常在框架(Framework)和大型应用中,在这种场景下和我们编写一个普通的程序,完成特定的功能,有着非常在的不同。
当我们只是写一段代码来完成特定的功能的时候,我们需要什么对象,就可以直接 new (创建)这个对象。
然而在大型应用,尤其是框架中,我们需要这个对象,但是这个对象的实现,却应该由框架的使用者来选择或者实现,此时,为了完成框架的功能,我们有必须需要这个对象。这就是一个变化点,此时就可以使用 创建型模式(Creational Design Pattern),将对象创建的过程封装起来。
例如,使用工厂方法的模式,将 inputTransport 和 outputTransport 对象的创建过程封装到 TTransportFactory 工厂类中。然后,将工厂类作为一个依赖。工厂类在创建 Server 时候就可以依据具体的应用场景确定好的。同时也可以提供一些配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 public void run () { TProcessor processor = null ; TTransport inputTransport = null ; TTransport outputTransport = null ; TProtocol inputProtocol = null ; TProtocol outputProtocol = null ; TServerEventHandler eventHandler = null ; ServerContext connectionContext = null ; try { processor = processorFactory_.getProcessor(client_); inputTransport = inputTransportFactory_.getTransport(client_); outputTransport = outputTransportFactory_.getTransport(client_); inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); outputProtocol = outputProtocolFactory_.getProtocol(outputTransport); while (true ) { eventHandler.processContext(connectionContext, inputTransport, outputTransport); if (stopped_ || !processor.process(inputProtocol, outputProtocol)) { break ; } } } catch (...) { } finally { } }
工厂方法的 Scope 是 Class , 就是因为工厂方法的目地就是可以动态指定创建对象的类型(Class)
$.参考
Thrift源码分析
Thrift Java Servers Compared