Thrift做为Facebook开源的RPC框架, 经过IDL中间语言, 并借助代码生成引擎生成各类主流语言的rpc框架服务端/客户端代码,主要特色:java
经过编写RPC接口IDL文件,利用编译生成器自动生成Server端骨架(Skeletons)和客户端Stubs,省去开发者自定义和维护接口编解码、消息传输、服务器多线程模型等基础工做;Server端开发者只需按照服务骨架,写好本身的业务处理程序(Handlers)便可,Client端程序只需建立IDL中定义的服务对象,而后就像调用本地对象的方法同样调用远端服务。node
经过维护Thrift格式的IDL(Interface Description Language)文件(注意写好注释),便可做为给Clients使用的接口文档使用,也自动生成接口代码,始终保持代码和文档的一致性。且Thrift协议可灵活支持接口的可扩展性。python
由于其来自Google Protocol Buffers开发团队,因此其IDL文件风格相似Google Protocol Buffers,且更加易读易懂;特别是RPC服务接口的风格就像写一个通常的面向对象的Class同样简单。c++
初学者只需参照http://thrift.apache.org/几个小时便可理解和使用Thrift。apache
Thrift支持C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi等多种语言,便可生成上述语言的服务器端和客户端程序。api
对于咱们常常使用的Java、PHP、Python、C++支持良好,虽然对iOS环境的Objective-C(Cocoa)支持稍逊,但也彻底知足咱们的使用要求。服务器
Thrift在不少开源项目中已经被验证是稳定和高效的,例如Cassandra、Evernode等;在Facebook、Baidu等后台产品中也有使用。网络
Thrift对软件栈的定义很是的清晰, 使得各个组件可以松散的耦合, 针对不一样的应用场景, 选择不一样是方式去搭建服务.
评注:
Transport: 传输层,定义数据传输方式,能够为TCP/IP传输,内存共享或者文件共享等
protocol: 协议层, 定义数据传输格式,能够为二进制或者XML等
Processor: 处理层, 这部分由定义的idl来生成, 封装了协议输入输出流, 并委托给用户实现的handler进行处理.
Server: 服务层, 整合上述组件, 提供网络模型(单线程/多线程/事件驱动), 最终造成真正的服务.多线程
Thrift和Google Protobuf相比, 都提供了可扩展序列化机制, 不但兼容性好并且压缩率高. 二者在这块各有长短, 性能上PB稍有优点. 但在语言的支持度上, Protobuf只支持c++/java/python这三种主流的语言, 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: 具体对应服务的类
namespace java com.yangyang.thrift.api service HelloService { string hello(1: string name); }
thrift -gen java -out ../java/ hello.thrift
在pom文件中加入thrift以及log4j的jar
<dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId> <version>0.9.3</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.5</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.5</version> </dependency>
编写服务端代码:
package com.yangyang.thrift.server; import com.yangyang.thrift.api.HelloService; import com.yangyang.thrift.com.yangyang.thrift.service.HelloServiceImpl; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.server.TServer; import org.apache.thrift.server.TThreadPoolServer; import org.apache.thrift.transport.TServerSocket; import org.apache.thrift.transport.TTransportException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Created by chenshunyang on 2016/10/30. */ public class ServerDemo { public static void main(String[] args) throws TTransportException { Logger logger = LoggerFactory.getLogger(ServerDemo.class); int port= 9000 ; // *) 传输层(Transport), 设置监听端口为9000 TServerSocket serverTransport = new TServerSocket(port); // *) 协议层 TBinaryProtocol.Factory protocolFactory = new TBinaryProtocol.Factory(true, true); // *) 处理层(Processor) HelloServiceImpl handler = new HelloServiceImpl(); HelloService.Processor<HelloServiceImpl> processor = new HelloService.Processor<HelloServiceImpl>(handler); // *) 服务层(Server) TServer server = new TThreadPoolServer( new TThreadPoolServer.Args(serverTransport) .protocolFactory(protocolFactory) .processor(processor)); // *) 启动监听服务 server.serve(); logger.info("服务已经启动,端口为:"+port); } }
编写客户端代码:
package com.yangyang.thrift; import com.yangyang.thrift.api.HelloService; 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; /** * Created by chenshunyang on 2016/10/30. */ public class ClientDemo { public static void main(String[] args) throws TException { // *) 传输层 TTransport transport = new TSocket("localhost", 9000); transport.open(); // *) 协议层, 与服务端对应 TProtocol protocol = new TBinaryProtocol(transport); // *) 建立RPC客户端 HelloService.Client client = new HelloService.Client(protocol); // *) 调用服务 System.out.println(client.hello("chenshunyang")); // *) 关闭句柄 transport.close(); } }
先运行服务端,后运行客户端,观察结果,能够看到客户端输出结果: hello chenshunyang