乐趣区

关于rpc:Thrift-框架的学习

因为一些历史起因须要在不同服务器之间建设 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 基本原理

退出移动版