简介
Thrift 是一种接口描述语言和二进制通讯协议, 它被用来定义和创建跨语言的服务. 它被当作远程过程调用 (RPC) 框架来使用, 是由 Facebook 为 "大规模跨语言服务开发" 而开发的. 它通过一个代码生成引擎联合了一个软件栈, 来创建不同程度的, 无缝的跨平台高效服务, 可以使用 C#,C++(基于 POSIX 兼容系统),Cappuccino,Cocoa,Delphi,Erlang,Go,Haskell,Java,Node.JS,OCaml,Perl,PHP,Python,Ruby 和 Smalltalk. 虽然它以前是由 Facebook 开发的, 但它现在是 Apache 软件基金会的开源项目了. 该实现被描述在 2007 年 4 月的一篇由 Facebook 发表的技术论文中, 该论文现由 Apache 掌管.
Thrift 包含完整的栈来创建客户端和服务端程序. 顶层部分是由 Thrift 定义生成的代码. 而服务则由这个文件客户端和处理器代码生成. 在生成的代码里会创建不同于内建类型的数据结构, 并将其作为结果发送. 协议和传输层是运行时库的一部分. 有了 Thrift, 就可以定义一个服务或改变通讯和传输协议, 而无需重新编译代码. 除了客户端部分之外, Thrift 还包括服务器基础设施来集成协议和传输, 如阻塞, 非阻塞及多线程服务器. 栈中作为 I/O 基础的部分对于不同的语言则有不同的实现.
Thrift 支持众多通讯协议:
TBinaryProtocol - 一种简单的二进制格式, 简单, 但没有为空间效率而优化. 比文本协议处理起来更快, 但更难于调试.
TCompactProtocol - 更紧凑的二进制格式, 处理起来通常同样高效.
TDebugProtocol - 一种人类可读的文本格式, 用来协助调试.
TDenseProtocol - 与 TCompactProtocol 类似, 将传输数据的元信息剥离.
TJSONProtocol - 使用 JSON 对数据编码.
TSimpleJSONProtocol - 一种只写协议, 它不能被 Thrift 解析, 因为它使用 JSON 时丢弃了元数据. 适合用脚本语言来解析.
支持的传输协议有:
TFileTransport - 该传输协议会写文件.
TFramedTransport - 当使用一个非阻塞服务器时, 要求使用这个传输协议. 它按帧来发送数据, 其中每一帧的开头是长度信息.
TMemoryTransport - 使用存储器映射输入输出.(Java 的实现使用了一个简单的 ByteArrayOutputStream.)
TSocket - 使用阻塞的套接字 I/O 来传输.
TZlibTransport - 用 zlib 执行压缩. 用于连接另一个传输协议.
Thrift 还提供众多的服务器, 包括:
TNonblockingServer - 多线程服务器, 它使用非阻塞 I/O(Java 的实现使用了 NIO 通道).TFramedTransport 必须跟这个服务器配套使用.
TSimpleServer - 单线程服务器, 它使用标准的阻塞 I/O. 测试时很有用.
TThreadPoolServer - 多线程服务器, 它使用标准的阻塞 I/O.
Thrift 一些已经明确的优点包括:
跟一些替代选择, 比如 SOAP 相比, 跨语言序列化的代价更低, 因为它使用二进制格式.
它有一个又瘦又干净的库, 没有编码框架, 没有 xml 配置文件.
绑定感觉很自然. 例如, Java 使用 java.util.ArrayList<String>;C++ 使用 std::vector<std::string>.
应用层通讯格式与序列化层通讯格式是完全分离的. 它们都可以独立修改.
预定义的序列化格式包括: 二进制格式, 对 HTTP 友好的格式, 以及紧凑的二进制格式.
兼作跨语言文件序列化.
协议使用软版本号机制软件版本管理. Thrift 不要求一个中心化的和显式的版本号机制, 例如主版本号 / 次版本号. 松耦合的团队可以轻松地控制 RPC 调用的演进.
没有构建依赖也不含非标准化的软件. 不存在不兼容的软件许可证混用的情况.
image.PNG
安装
以 Ubuntu 为例
- # apt install thrift-compiler
- # pip3 install thrift
快速入门
定义接口文档
- service Example {
- string ping(),
- void say(1:string msg)
- }
服务器端 server.py
- from thrift.transport import TSocket
- from thrift.transport import TTransport
- from thrift.protocol import TBinaryProtocol
- from thrift.server import TServer
- from pygen.example import Example
- class ExampleHandler:
- def __init__(self):
- self.log = {}
- def ping(self):
- return "pong"
- def say(self, msg):
- print(msg)
- handler = ExampleHandler()
- processor = Example.Processor(handler)
- transport = TSocket.TServerSocket(port=30303)
- tfactory = TTransport.TBufferedTransportFactory()
- pfactory = TBinaryProtocol.TBinaryProtocolFactory()
- server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
- print("Starting python server...")
- server.serve()
- print("done!")
客户端 client.py
- from thrift import Thrift
- from thrift.transport import TSocket
- from thrift.transport import TTransport
- from thrift.protocol import TBinaryProtocol
- from pygen.example import Example
- try:
- transport = TSocket.TSocket('localhost', 30303)
- transport = TTransport.TBufferedTransport(transport)
- protocol = TBinaryProtocol.TBinaryProtocol(transport)
- client = Example.Client(protocol)
- transport.open()
- print(client.ping())
- client.say('Hello from Python!')
- transport.close()
- except Thrift.TException as tx:
- print(tx.message)
执行:
- $ thrift -out pygen/ --gen py example.thrift
- $ python3 server.py
- Starting python server...
- Hello from Python!
- $ python3 client.py
- pong
来源: http://www.jianshu.com/p/ca9dc8e0ddcd