thrift实战教程

简介

Thrift最初由Facebook研发,主要用于各个服务之间的RPC通信,支持跨语言,常用的语言比如C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml都支持。Thrift是一个典型的**CS(客户端/服务端)**结构,客户端和服务端可以使用不同的语言开发。既然客户端和服务端能使用不同的语言开发,那么一定就要有一种中间语言来关联客户端和服务端的语言,没错,这种语言就是IDL(Interface Description Language)

thrift使用流程

  1. 明确要交互的数据格式和具体的方法,定义出thrift接口描述文件(英文叫做IntefaceDescription File)

  2. 调用thrift工具,依据thrift接口文件,生成RPC代码;

  3. 你的服务器端程序引用thrift生成的RPC代码,并实现其中的Search动作的逻辑,然后启动监听,等待客户端发来请求。

  4. 客户端同样引入并调用RPC代码来与服务器端通信

thrift IDL

###1. 基本类型
thrift不支持无符号类型,因为很多编程语言不存在无符号类型,比如java

  • bool: 布尔类型(True or False)
  • byte: 有符号字节
  • i16: 16位有符号整数
  • i32: 32位有符号整数
  • i64: 64位有符号整数
  • double: 64位浮点数
  • string: 字符串

###2. 容器类型
集合中的元素可以是除了service之外的任何类型,包括exception。

  • list : 一系列由T类型的数据组成的有序列表,元素可以重复。会被转换成C++中的vector,Java中的ArrayList,脚本语言中的数组等。
  • set: 一系列由T类型的数据组成的无序集合,元素不可重复。会转换成C++中的set,Java中的HashSet、Python中的Set等
  • map: 一个字典结构,key为K类型,value为V类型,相当于Java中的HMap。一个含有多个key:value键值对的结构。会被转换成C++中的map,Java中的HashMap,PHP中的关联数组,Python/Ruby中的dictionary等

###3. 结构体
就像C语言一样,thrift也支持struct类型,目的就是将一些数据聚合在一起,方便传输管理。struct的定 义形式如下:

struct People {
     1: required string name;
     2: required i32 age = 20;
     3: optional string sex;
}

可以看到,结构体中每一个域都有一个正整数标识符,这个标识符并不要求连续,但一旦定义,不建议再进行修改
另外,每个域前都会有required或optional的限定,前者表示是必填域,后者则表示是可选域。域是可以有默认值的,比如上例中的“age"。
如果一个域设置为optional且在构造结构体时没有给这个域赋值,那么在使用这个结构体时,就会忽略掉这个optional的域

异常(exception)

thrift支持自定义exception,规则和struct一样,如下:

exception RequestException {
    1: i32 code;
    2: string reason;
}

除了使用exception来替代struct以外,“异常”这个类型,在语法上和刚才介绍过的结构体的用法是完全一致的。但是从语义上讲,exception和struct却大相径庭。exception是在远程调用发生异常时用来抛出异常用的

服务(Service)

服务的定义,与面向对象技术中定义一个接口很类似,而这些接口其实就是纯虚函数。thrift编译工具会根据服务的定义来产生相应的方法和函数。
每个服务,都包括了若干个函数,每个函数包括了若干参数和一个返回值(返回值可以是void.
(小技巧:返回值为void的函数,你可以在函数名前加上oneway标识符,将此函数以异步模式执行,这样在调用此函数后,函数会立即返回。)

对于返回void的函数,thrift仍然会确保函数返回,这样就表示这个函数已被正确执行,且服务器端已有返回信息了。但是如果给void的函数前加上oneway,那么此函数的返回只能表示数据已经进入传输层,并不能表示服务器端已经收到并返回了数据

service vulgar_detect{
    bool is_vulgar(1:string title),
    i32 calc(1: i32 num)
}

thrift编译工具

在我们编写好thrift接口描述文件之后,thrift编译工具就要派上用场了,它的作用就是根据thrift接口描述文件来生成相应开发语言的RPC代码.
在终端下输入:

thrift --gen ${开发语言} ${thrift接口描述文件}

关于thrift的更多命令可以输入

thrift --help

实战

说了这么多,我们来看个例子加深印象。

###1. 接口文件demo.thrift

service demo{
    string repeat2(1:string msg),
    i16 calc(1:i16 num1)
}

###2. 编辑服务端sever.rpy

# coding:utf-8
import sys,os
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
curPath = os.path.abspath(os.path.dirname(__file__))
rootPath = os.path.split(curPath)[0]
sys.path.append(rootPath)
from pygen.demo import demo


class demoHandler:
    def __init__(self):
        pass
    def repeat2(self, msg):
        return msg * 2

    def calc(self, num1):
        return (num1**2)


handler = demoHandler()
processor = demo.Processor(handler)
# 设定主机和端口号
transport = TSocket.TServerSocket(host='localhost',port=30303)
# 选择传输层(和客户端保持一致)
tfactory = TTransport.TBufferedTransportFactory()
# 选择传输协议(和客户端保持一致)
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
# 创建服务端
server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
print("Starting python server...")
# 开启服务
server.serve()
print("done!")

###3. 编辑客户端

# coding:utf-8
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol

from pygen.demo import demo


try:
    # 设定主机和端口号
    transport = TSocket.TSocket('localhost', 30303)
    # 选择传输层(和服务端保持一致)
    transport = TTransport.TBufferedTransport(transport)
    # 选择传输协议(和服务端保持一致)
    protocol = TBinaryProtocol.TBinaryProtocol(transport)
    # 创建客户端
    client = demo.Client(protocol)
    # 开启传输
    transport.open()
    # 发起请求
    print(client.repeat2('first thrift demo'))
    print(client.calc(72))
    # 关闭传输
    transport.close()

except Thrift.TException as tx:
    print(tx.message)

以上三个文件都在同一目录下
使用如下生产rpc代码,将生成的gen-py重命名为pygen

thrift --gen py demo.thrift
python server.py #开启服务
python client.py # 发起请求

你可能感兴趣的:(技术工具,python,thrift,rpc)