thrift入门实例
简单实现say hello的RPC服务
比如你现在有一套代码,只有一个简单的Hello
类,你想使用thrift实现RPC的客户端和服务端业务,让客户端向服务端打招呼,say hello
。
filename: h.py(注意是h.py不要写成hello.py,博主写的时候命名冲突了,注意此处写成h.py)
class Hello:
def hello_kitty(self):
print("hello kitty")
def hello_py(self):
print("hello py")
在Hello
类定义好之后,紧接着第二步是根据你的Hello
类编写hello.thrift
文件,由于你的业务里只实现了一个Hello类,没有常量以及复杂的数据类型(结构体、枚举、异常类型),所以这里只在hello.thrift
文件编写Hello
类对应的服务。
filename: hello.thrift
service Hello{
void hello_kitty(),
void hello_py()
}
现在hello.thrift
文件写好了,进行第三步:通过hello.thrift
文件生成对应的python代码。执行命令:
thrift -r --gen py hello.thrift
命令执行完之后,会生成gen-py目录,里面的代码文件是根据hello.thfirt
定义的服务,自动生成的客户端和服务端的RPC服务处理逻辑。
博主的以上操作如下图所示,可以看到生成之后的文件:
thrift生成的文件
如图所示,通过thrift生成的代码结构,可以看到有五个文件组成。
ttpyes.py
以类的形式表示thrift定义的复杂数据类型:结构体、枚举、异常类型;
constants.py
顾名思义,该文件存储thrift定义的常量;
Hello.py
这个文件中的Client/Processor
类才是客户端和服务端处理具体RPC业务的逻辑代码。
细心的同学会发现,Iface
中定义的方法对应着hello.thrift
定义的服务中的方法。实际上Iface
类相当于一个接口,对应着本地的具体业务逻辑。
Hello-remote
一个脚本文件
编写server.py和client.py
当然是先编写服务端咯
server.py
import sys
sys.path.append('gen-py')
from hello import Hello as ThriftHello
from h import Hello as ClassHello
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
if __name__ == '__main__':
handler = ClassHello()
processor = ThriftHello.Processor(handler)
transport = TSocket.TServerSocket(host='0.0.0.0', port=8080)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
# You could do one of these for a multithreaded server
# server = TServer.TThreadedServer(
# processor, transport, tfactory, pfactory)
server.serve()
client.py
import sys
sys.path.append('gen-py')
from hello import Hello as ThriftHello
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
def main():
# Make socket
transport = TSocket.TSocket('0.0.0.0', 8080)
# Buffering is critical. Raw sockets are very slow
transport = TTransport.TBufferedTransport(transport)
# Wrap in a protocol
protocol = TBinaryProtocol.TBinaryProtocol(transport)
# Create a client to use the protocol encoder
client = ThriftHello.Client(protocol)
# Connect!
transport.open()
client.hello_kitty()
print('done hello kitty!')
client.hello_py()
print('done hello py!')
# close!
transport.close()
if __name__ == '__main__':
main()
运行实例
python server.py
python client.py
服务端负责监听客户端的请求,客户端启动之后向服务端say hello。
实例运行结果
client result
server result
番外
博主也是一气呵成练了一把手,第一个完整的实例,还有很多不懂的东西需要学习。在编写客户端代码的时候,我写成了这样
# connect!
transport.open()
...
# close!
#client.close()
transport.close()
# 粗心把 transport.close() 写成了 client.close(),
# ------
# 客户端/服务端这些代码的实际意义就是thrift为服务端和客户端建立一个传输通道(transport),
# 客户端和服务端达成某种协议之后(protocol),再通过这个通道通信。