本文主要简单记录rpc框架thrift的使用,详细可查thrift官网
第一步:安装thrift
命令行输入 brew install thrift (此方法仅适用于mac,其他安装方法查看教程)
第二步:编写一个.thrift文件
首先这个.thrift文件是什么作用呢?其实这个文件主要用类c语言的写法定义一些常量、结构、类和方法。
然后为什么要定义这个.thrift文件呢? 我们知道thrift RPC框架是可以支持20多中语言的如python、java、go、php、C++等,我们需要定义这个.thrift文件,然后通过thrift程序把它转换成你需要语言的格式,也就是我们第三步要做的。
这里我们写个rpc.thirft文件示例:
namespace py rpc namespace java rpc namespace go rpc
//上面内容可以省略
//定义常量示例 const string HELLO_WORLD = "world"
//定义结构体示例 struct Resp{ 1: i32 Code=0, 2: string Msg="", }
//定义接口示例 service HelloWorld { void ping(), //接口方法 Resp sayHello(), /接口的返回值为Resp结构体形式 string sayMsg(1:string msg) }
第三步:把根据我们定义的.thrift文件,thrift自动生成代码
命令行输入
thrift --gen <language> <Thrift filename>
例如我们是python语言,然后文件名为rpc.thrift所以我们输入命令
thrift --gen py pc.thrift
在你输入完命令刷新后,会自动出现gen-py目录,我们可以将它理解为我们RPC程序的脚手架
第四步:有了脚手架后,我们就可以编写客户端和服务端了
客户端文件示例 client.py:
import sys sys.path.append('./gen-py') from rpc import HelloWorld from rpc.ttypes import * from rpc.constants import * from thrift import Thrift from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol try: # Make socket transport = TSocket.TSocket('127.0.0.1', 30303) # 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 = HelloWorld.Client(protocol) # Connect! transport.open() client.ping() print("ping()") msg = client.sayHello() print(msg, type(msg))
# 这里发送的是之前文件中定义的常量HELLO_WORD msg = client.sayMsg(HELLO_WORLD) print(msg) transport.close() except Thrift.TException as tx: print("%s" % (tx.message))
然后编写服务端程序service.py:
import sys sys.path.append('./gen-py') from rpc import HelloWorld from rpc.ttypes import * from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from thrift.server import TServer import socket class HelloWorldHandler: def __init__(self): self.log = {} def ping(self): print("ping()") def sayHello(self): print("sayHello()") # 这里我返回的是之前定义的Resp结构体 return Resp(1, "hahah") def sayMsg(self, msg): print(1212) return msg handler = HelloWorldHandler() processor = HelloWorld.Processor(handler) transport = TSocket.TServerSocket('127.0.0.1', 30303) tfactory = TTransport.TBufferedTransportFactory() pfactory = TBinaryProtocol.TBinaryProtocolFactory() server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) print("Starting python server...") server.serve() print("done!")
这两个文件放在gen-py目录下
第五步:先启动service端,然后再启动client端
然后你查看控制台就可以看到,客户端与服务端之间的通信输出了如:
service端:
/usr/local/bin/python3.7 /Users/bytedance/PycharmProjects/untitled5_django/rpc/service.py
Starting python server...
ping()
sayHello()
1212
client端输出:
/usr/local/bin/python3.7 /Users/bytedance/PycharmProjects/untitled5_django/rpc/client.py ping() Resp(Code=1, Msg='hahah') <class 'rpc.ttypes.Resp'> world Process finished with exit code 0