本文主要簡單記錄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