因为一些历史起因须要在不同服务器之间建设 rpc 通道,来满足不定时、不定量且数据量可能会大的函数须要。在简略比照了之后投向了 thrift,尽管网上大佬们说 thrift 的文档做的很烂,但具体有多烂这个我也不晓得,可能根底需要来讲也不重要。
Q: 为什么抉择 rpc 而不是 RESTful API 的形式?
A:
资源粒度 。RPC 就像本地办法调用,RESTful API 每一次增加接口都可能须要额定地组织凋谢接口的数据,这相当于在利用视图中再写了一次办法调用,而且它还须要保护开发接口的资源粒度、权限等;
流量耗费。RESTful API 在应用层应用 HTTP 协定,哪怕应用轻型、高效、传输效率高的 JSON 也会耗费较大的流量,而 RPC 传输既能够应用 TCP 也能够应用 UDP,而且协定个别应用二制度编码,大大降低了数据的大小,缩小流量耗费。
Thrift 的网络栈构造:
上面两层的数据传输:
TTransport 层
代表 thrift 的数据传输方式,thrift 定义了如下几种罕用数据传输方式
TSocket
: 阻塞式 socket;TFramedTransport
: 以 frame 为单位进行传输,非阻塞式服务中应用;TFileTransport
: 以文件模式进行传输;
TProtocol 层
代表 thrift 客户端和服务端之间传输数据的协定,艰深来讲就是客户端和服务端之间传输数据的格局(例如 json 等),thrift 定义了如下几种常见的格局
TBinaryProtocol
: 二进制格局;TCompactProtocol
: 压缩格局;TJSONProtocol
: JSON 格局;TSimpleJSONProtocol
: 提供只写的 JSON 协定;
thrift 反对的 Server 模型
thrift 次要反对以下几种服务模型
TSimpleServer
: 简略的单线程服务模型,罕用于测试;TThreadPoolServer
: 多线程服务模型,应用规范的阻塞式 IO;TNonBlockingServer
: 多线程服务模型,应用非阻塞式 IO(须要应用TFramedTransport
数据传输方式);THsHaServer
:THsHa
引入了线程池去解决,其模型读写工作放到线程池去解决,Half-sync/Half-async
解决模式,Half-async
是在解决 IO 事件上 (accept/read/write io),Half-sync
用于 handler 对 rpc 的同步解决;
thrift IDL 文件
thrift IDL 不反对无符号的数据类型,因为很多编程语言中不存在无符号类型,thrift 反对以下几种根本的数据类型
byte
: 有符号字节i16
: 16 位有符号整数i32
: 32 位有符号整数i64
: 63 位有符号整数double
: 64 位浮点数string
: 字符串
此外 thrift 还反对以下容器类型:
list
: 一系列由 T 类型的数据组成的有序列表,元素能够反复;set
: 一系列由 T 类型的数据组成的无序汇合,元素不可反复;map
: 一个字典构造,Key 为 K 类型,Value 为 V 类型,相当于 java 中的 HashMap;
应用 python 编写 thrift 客户端代码
执行 thrift --gen py src/thrift/data.thrift
生成对应的 python
代码, 并引入到 python 工程当中,代码构造如下图所示
python 客户端代码
# -*- coding:utf-8 -*-
__author__ = 'kpzhang'
from py.thrift.generated import PersonService
from py.thrift.generated import ttypes
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TCompactProtocol
import sys
reload(sys)
sys.setdefaultencoding('utf8')
try:
tSocket = TSocket.TSocket("localhost", 8899)
tSocket.setTimeout(900)
transport = TTransport.TFramedTransport(tSocket)
protocol = TCompactProtocol.TCompactProtocol(transport)
client = PersonService.Client(protocol)
transport.open()
person = client.getPersonByUsername("张三")
print person.username
print person.age
print person.married
print '---------------------'
newPerson = ttypes.Person();
newPerson.username = "李四"
newPerson.age = 30
newPerson.married = True
client.savePerson(newPerson)
transport.close()
except Thrift.TException, tx:
print '%s' % tx.message
参考:
thrift 基本原理