因为一些历史起因须要在不同服务器之间建设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 PersonServicefrom py.thrift.generated import ttypesfrom thrift import Thriftfrom  thrift.transport import TSocketfrom  thrift.transport import TTransportfrom  thrift.protocol import TCompactProtocolimport sysreload(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基本原理