投资建设集团网站首页,成都青白江网站建设,wordpress walker,建立良好的公共秩序教学设计文章目录前言正文Thrift的技术栈Thrift的特性(一) 开发速度快(二) 接口维护简单(三) 学习成本低(四) 多语言/跨语言支持(五) 稳定/广泛使用Thrift的数据类型Thrift的协议Thrift的传输层Thrift的服务端类型Thrift入门示例(一) 编写Thrift IDL文件(二) 新建Maven工程总结前言
Th…
文章目录前言正文Thrift的技术栈Thrift的特性(一) 开发速度快(二) 接口维护简单(三) 学习成本低(四) 多语言/跨语言支持(五) 稳定/广泛使用Thrift的数据类型Thrift的协议Thrift的传输层Thrift的服务端类型Thrift入门示例(一) 编写Thrift IDL文件(二) 新建Maven工程总结前言
Thrift读音[θrɪft]是一个轻量级、跨语言的远程服务调用框架最初由Facebook开发后面进入Apache开源项目。它通过自身的IDL中间语言, 并借助代码生成引擎生成各种主流语言的RPC服务端/客户端模板代码。
Thrift支持多种不同的编程语言包括C、Java、Python、PHP、Ruby等本系列主要讲述基于Java语言的Thrift的配置方式和具体使用。
正文
Thrift的技术栈
Thrift对软件栈的定义非常的清晰, 使得各个组件能够松散的耦合, 针对不同的应用场景, 选择不同是方式去搭建服务。
Thrift软件栈分层从下向上分别为传输层(Transport Layer)、协议层(Protocol Layer)、处理层(Processor Layer)和服务层(Server Layer)。 传输层(Transport Layer)传输层负责直接从网络中读取和写入数据它定义了具体的网络传输协议比如说TCP/IP传输等。 协议层(Protocol Layer)协议层定义了数据传输格式负责网络传输数据的序列化和反序列化比如说JSON、XML、二进制数据等。 处理层(Processor Layer)处理层是由具体的IDL接口描述语言生成的封装了具体的底层网络传输和序列化方式并委托给用户实现的Handler进行处理。 服务层(Server Layer)整合上述组件提供具体的网络线程/IO服务模型形成最终的服务。
Thrift的特性
(一) 开发速度快
通过编写RPC接口Thrift IDL文件利用编译生成器自动生成服务端骨架(Skeletons)和客户端桩(Stubs)。从而省去开发者自定义和维护接口编解码、消息传输、服务器多线程模型等基础工作。
服务端只需要按照服务骨架即接口编写好具体的业务处理程序(Handler)即实现类即可。客户端只需要拷贝IDL定义好的客户端桩和服务对象然后就像调用本地对象的方法一样调用远端服务。
(二) 接口维护简单
通过维护Thrift格式的IDL接口描述语言文件注意写好注释即可作为给Client使用的接口文档使用也自动生成接口代码始终保持代码和文档的一致性。且Thrift协议可灵活支持接口的可扩展性。
(三) 学习成本低
因为其来自Google Protobuf开发团队所以其IDL文件风格类似Google Protobuf且更加易读易懂特别是RPC服务接口的风格就像写一个面向对象的Class一样简单。 初学者只需参照thrift.apache.org/一个多小时就可以理解Thrift IDL文件的语法使用。
(四) 多语言/跨语言支持
Thrift支持C、 Java、Python、PHP、Ruby、Erlang、Perl、Haskell、C#、Cocoa、JavaScript、Node.js、Smalltalk等多种语言即可生成上述语言的服务器端和客户端程序。 对于我们经常使用的Java、PHP、Python、C支持良好虽然对iOS环境的Objective-C(Cocoa)支持稍逊但也完全满足我们的使用要求。
(五) 稳定/广泛使用
Thrift在很多开源项目中已经被验证是稳定和高效的例如Cassandra、Hadoop、HBase等国外在Facebook中有广泛使用国内包括百度、美团小米、和饿了么等公司。
Thrift的数据类型
Thrift 脚本可定义的数据类型包括以下几种类型 基本类型 bool: 布尔值byte: 8位有符号整数i16: 16位有符号整数i32: 32位有符号整数i64: 64位有符号整数double: 64位浮点数string: UTF-8编码的字符串binary: 二进制串 结构体类型 struct: 定义的结构体对象 容器类型 list: 有序元素列表set: 无序无重复元素集合map: 有序的key/value集合 异常类型 exception: 异常类型 服务类型 service: 具体对应服务的类
Thrift的协议
Thrift可以让用户选择客户端与服务端之间传输通信协议的类别在传输协议上总体划分为文本(text)和二进制(binary)传输协议。为节约带宽提高传输效率一般情况下使用二进制类型的传输协议为多数有时还会使用基于文本类型的协议这需要根据项目/产品中的实际需求。常用协议有以下几种
TBinaryProtocol二进制编码格式进行数据传输TCompactProtocol高效率的、密集的二进制编码格式进行数据传输TJSONProtocol 使用JSON文本的数据编码协议进行数据传输TSimpleJSONProtocol只提供JSON只写的协议适用于通过脚本语言解析
Thrift的传输层
常用的传输层有以下几种
TSocket使用阻塞式I/O进行传输是最常见的模式TNonblockingTransport使用非阻塞方式用于构建异步客户端TFramedTransport使用非阻塞方式按块的大小进行传输类似于Java中的NIO
Thrift的服务端类型
TSimpleServer单线程服务器端使用标准的阻塞式I/OTThreadPoolServer多线程服务器端使用标准的阻塞式I/OTNonblockingServer单线程服务器端使用非阻塞式I/OTHsHaServer半同步半异步服务器端基于非阻塞式IO读写和多线程工作任务处理TThreadedSelectorServer多线程选择器服务器端对THsHaServer在异步IO模型上进行增强
Thrift入门示例
(一) 编写Thrift IDL文件
a). 下载0.10.0的Thrift IDL编译器下载地址http://thrift.apache.org/docs/install。 通过编译生成器生成.java接口的类文件。
b). 下载Windows安装环境的.exe文件将thrift.exe的路径加入环境变量中。在Idea上安装Thrift编辑插件。
c). 编写hello.thrift的IDL文件
service HelloWorldService {string say(1: string username)
}d). 使用代码生成工具生成代码执行以下命令
thrift -gen java hello.thrifte). 由于未指定代码生成的目标目录生成的类文件默认存放在gen-java目录下。这里生成一个HelloWorldService.java类文件文件大小超过数千行下面截取一部分核心代码。
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.AsyncMethodCallbackString 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.TServiceClientFactoryClient {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.TAsyncClientFactoryAsyncClient {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.AsyncMethodCallbackString 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);}// 省略.....}// 省略.....
}对于开发人员而言使用原生的Thrift框架仅需要关注以下四个核心内部接口/类Iface, AsyncIface, Client和AsyncClient。
Iface服务端通过实现HelloWorldService.Iface接口向客户端的提供具体的同步业务逻辑。AsyncIface服务端通过实现HelloWorldService.Iface接口向客户端的提供具体的异步业务逻辑。Client客户端通过HelloWorldService.Client的实例对象以同步的方式访问服务端提供的服务方法。AsyncClient客户端通过HelloWorldService.AsyncClient的实例对象以异步的方式访问服务端提供的服务方法。
(二) 新建Maven工程
a). 新建maven工程引入thrift的依赖这里使用的是版本0.10.0。 dependencygroupIdorg.apache.thrift/groupIdartifactIdlibthrift/artifactIdversion0.10.0/version/dependencyb). 将生成类的HelloWorldService.java源文件拷贝进项目源文件目录中并实现HelloWorldService.Iface的定义的say()方法。
HelloWorldServiceImpl.java
public class HelloWorldServiceImpl implements HelloWorldService.Iface {Overridepublic String say(String username) throws TException {return Hello username;}
}c). 服务器端程序编写 SimpleServer.java
public class SimpleServer {public static void main(String[] args) throws Exception {ServerSocket serverSocket new ServerSocket(ServerConfig.SERVER_PORT);TServerSocket serverTransport new TServerSocket(serverSocket);HelloWorldService.Processor processor new HelloWorldService.ProcessorHelloWorldService.Iface(new HelloWorldServiceImpl());TBinaryProtocol.Factory protocolFactory new TBinaryProtocol.Factory();TSimpleServer.Args tArgs new TSimpleServer.Args(serverTransport);tArgs.processor(processor);tArgs.protocolFactory(protocolFactory);// 简单的单线程服务模型 一般用于测试TServer tServer new TSimpleServer(tArgs);System.out.println(Running Simple Server);tServer.serve();}
}d). 客户端程序编写 SimpleClient.java
public class SimpleClient {public static void main(String[] args) {TTransport transport null;try {transport new TSocket(ServerConfig.SERVER_IP, ServerConfig.SERVER_PORT, ServerConfig.TIMEOUT);TProtocol protocol new TBinaryProtocol(transport);HelloWorldService.Client client new HelloWorldService.Client(protocol);transport.open();String result client.say(Leo);System.out.println(Result : result);} catch (TException e) {e.printStackTrace();} finally {if (null ! transport) {transport.close();}}}
}e). 运行服务端程序服务端在指定端口监听客户端的连接请求控制台输出启动日志
f). 运行客户端程序客户端通过网络请求HelloWorldService的say()方法的具体实现控制台输出返回结果
这里使用的一个基于单线程同步的简单服务模型一般仅用于入门学习和测试
总结
本文对Thrift的概念做了相关介绍体验了一番thrift程序如何编写