本文使用的工具是饿了么开发的thriftpygunicorn_thrift

简介

thrift

首先thrift是啥呢?thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Go,Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。

RPC

说thrift不得不提的是RPC, RPC(Remote Procedure Call Protocol) 远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

应用

其实thrift是一种开源的跨语言的RPC服务框架,可以基于它进行RPC请求等的处理,而不用进行HTTP请求,减少资源消耗,提高效率。用于微服务是极好的,特别是数据量大的请求。

与HTTP的性能比较

thrift 体积超小,使用起来比较麻烦,不如json容易,但是对于1.高并发、2.数据传输量大、3.多语言环境 比较适合。

假定需要传输相同的内容,但使用不同的方式从 1、传输内容所产生的大小 2、传输过程中服务端和客户端所产生的开销,这2个方面进行比较,如下:

开始使用

thrift文件

首先定义thrift文件,这个文件相当于一个协议,在客户端和服务器都应该包含这个文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
service Calc {
truestring tdx_ability(
truetrue1: string fundId,
truetrue),
truestring tdx_ability_status(),
truestring tdx_increment(),
truestring signal_ability(),
truestring sync_ability(
truetrue1: string fundId,
truetrue2: string assets,
truetrue3: string flows,
truetrue4: string stocks,
truetrue5: string start,
truetrue6: string stop,
truetrue7: string calc_type,)
}
service Read {
truestring summary(),
truestring prices(),
truestring ability()
}

其中Calc和Read定义为两个服务,服务底下有多个函数,函数定义为返回值类型,函数名,函数参数

服务器

下来创建一个服务器,这里有多个服务,因此需要创建多个服务处理器,同时需要指定视情况而需要的协议和传输类型,最后选择需要的服务器。

我们这里选择了TJSONProtocolFactory()TBufferedTransportFactory(),服务器使用了gunicorn_thrift,后面会详细介绍这些东西。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import thriftpy
import os
from thriftpy.transport import TServerSocket
from thriftpy.thrift import TMultiplexedProcessor
from thriftpy.rpc import TProcessor
from config import THRIFT_HOST, THRIFT_PORT
from .calc_ability import CalcAbility
from .read_ability import ReadAbility
dir_path = os.path.abspath(os.path.dirname(__file__))
thrift_path = os.path.join(dir_path, 'ability.thrift')
# 导入thrift文件
ability_thrift = thriftpy.load(thrift_path, module_name="ability_thrift")
# 创建socket
server_socket = TServerSocket(host=THRIFT_HOST, port=THRIFT_PORT, client_timeout=None)
# 创建thrift的主应用,这里的应用可以为多个服务注册多个处理器
thrift_app = TMultiplexedProcessor()
# 为每个服务创建处理器
calc_processor = TProcessor(ability_thrift.Calc, CalcAbility())
read_processor = TProcessor(ability_thrift.Read, ReadAbility())
# 在thrift主应用中注册这些处理器
thrift_app.register_processor('ability_thrift.Calc', calc_processor)
thrift_app.register_processor('ability_thrift.Read', read_processor)

这样就创建了一个thrift应用,然后需要指定服务器,这里我们使用gunicorn_thrift,其实thriftpy里面有许多简单的服务器,比如单线程服务器,多线程服务器,但是这些服务器并不能满足生产需要。

启动gunicorn服务器:gunicorn_thrift thrift_abi:thrift_app -k thriftpy_sync --thrift-protocol-factory thriftpy.protocol:TJSONProtocolFactory --thrift-transport-factory thriftpy.transport:TBufferedTransportFactory

-k参数指定是同步还是异步,另外需要指定协议和传输方式

客户端

客户端就比较容易了,只需要导入thrift文件,并且根据协议和传输方式创建客户端就行了,然后客户端就可以远程调用服务器的方法函数了。

1
2
3
4
5
6
7
8
9
import thriftpy
from thriftpy.protocol import TJSONProtocolFactory, TMultiplexedProtocolFactory
from thriftpy.transport import TBufferedTransportFactory
from thriftpy.rpc import make_client
ability_thrift = thriftpy.load("ability.thrift", module_name="ability_thrift")
client = make_client(ability_thrift.Calc, '127.0.0.1', 5004, proto_factory=TMultiplexedProtocolFactory(TJSONProtocolFactory(), 'ability_thrift.Calc'), trans_factory=TBufferedTransportFactory())
client.tdx_ability()

小结

thrift的使用是比直接HTTP请求要麻烦一点,并且如果服务器要改动函数签名,就需要更改thrift文件,并且客户端也需要同步,并且修改签名,但是这样的方式在微服务架构中带来的性能提升是很大的,值得作出这样的改变。

剧透

下一节将对thriftpy中的核心组件进行解析。