python實現一個簡單RPC框架的示例
本文需要一點Python socket基礎。
回顧RPC
實現jsonrpc
在實現前,簡單理一下整體思路。
1、Network Service 直接使用Python Socket相關的API實現 2.傳輸數據使用JSON,在Socket層會被壓成二進制,我們無需關心。
模仿xmlrpc,Client與Server都采用Minix多繼承機制來實現,每個類負責自身的事情,最終暴露出現的只有一個類中有限的方法。
先從Client端開始實現。
# client.py import rpcclient c = rpcclient.RPCClient()c.connect(’127.0.0.1’, 5000)res = c.add(1, 2, c=3)print(f’res: [{res}]’)
實例化rpcclient.RPCClient類,然后調用connect方法鏈接Server端,隨后直接調用Server端的add方法,該方法的效果就是將傳入的數據進行累加并將累加的結果返回,最后將add方法返回的結果打印出了。
RPCClient類繼承于TCPClient類與RPCStub類。
# rpclient.pyclass RPCClient(TCPClient, RPCStub): pass
其中TCPClient負責通過Socket實現TCP鏈接并將數據請求過去,而RPCStub類主要將Client端調用Server端方法的相關信息打包,然后調用TCPClient類中的方法發送則可,兩個類同樣實現在rpclient.py文件中,代碼如下。
class TCPClient(object): def __init__(self):self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def connect(self, host, port):’’’鏈接Server端’’’self.sock.connect((host, port)) def send(self, data):’’’將數據發送到Server端’’’self.sock.send(data) def recv(self, length):’’’接受Server端回傳的數據’’’return self.sock.recv(length) class RPCStub(object): def __getattr__(self, function):def _func(*args, **kwargs): d = {’method_name’: function, ’method_args’: args, ’method_kwargs’: kwargs} self.send(json.dumps(d).encode(’utf-8’)) # 發送數據 data = self.recv(1024) # 接收方法執行后返回的結果 return data setattr(self, function, _func)return _func
TCPClient類就是常規的Socket API的操作,無需多言,主要看看RPCStub類。
當我們在Client端調用res = c.add(1, 2, c=3)時,會執行RPCStub中的__getattr__方法,該方法會將Client端調用的方法、參數等信息通過TCPServer類的send方法發送,發送數據進行了JSON格式化,方便Server端解碼,隨后便調用recv方法等待Server端相應的數據返回。
因為RPCClient類本身沒有add方法,為了讓用戶做到Client端直接調用Server端方法的形式,先利用__getattr__構建了_func方法,并將其通過setattr方法設置到RPCClient類中,此時該類就有Server端方法對應的映射了。
調用add方法,就調用了對應的_func方法,將數據發送至Server端。
Client端就這樣搞定了,接著來實現Server端,不用緊張,非常簡單。
Server端的使用方式如下。
# server.py import rpcserver def add(a, b, c=10): sum = a + b + c return sum s = rpcserver.RPCServer()s.register_function(add) # 注冊方法s.loop(5000) # 傳入要監聽的端口
實例化rpcserver.RPCServer類,然后通過register_function方法將想被Client端調用的方法傳入,隨后調用loop方法,將要監聽的端口傳入,RPCServer類的實現如下。
# rpcserver.py class RPCServer(TCPServer, JSONRPC, RPCStub): def __init__(self):TCPServer.__init__(self)JSONRPC.__init__(self)RPCStub.__init__(self) def loop(self, port):# 循環監聽 5000 端口self.bind_listen(port)print(’Server listen 5000 ...’)while True: self.accept_receive_close() def on_msg(self, data):return self.call_method(data)
RPCServer繼承自TCPServer、JSONRPC、RPCStub,這些類同樣實現在rpcserver.py文件中并且給出了詳細的注釋,所以就詳細解釋了。
class TCPServer(object): def __init__(self):self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def bind_listen(self, port):self.sock.bind((’0.0.0.0’, port))self.sock.listen(5) def accept_receive_close(self):’’’獲取Client端信息’’’(client_socket, address) = self.sock.accept()msg = client_socket.recv(1024)data = self.on_msg(msg)client_socket.sendall(data) # 回傳client_socket.close() class JSONRPC(object): def __init__(self):self.data = None def from_data(self, data):’’’解析數據’’’self.data = json.loads(data.decode(’utf-8’)) def call_method(self, data):’’’解析數據,調用對應的方法變將該方法執行結果返回’’’self.from_data(data)method_name = self.data[’method_name’]method_args = self.data[’method_args’]method_kwargs = self.data[’method_kwargs’]res = self.funs[method_name](*method_args, **method_kwargs)data = {'res': res}return json.dumps(data).encode(’utf-8’) class RPCStub(object): def __init__(self):self.funs = {} def register_function(self, function, name=None):’’’Server端方法注冊,Client端只可調用被注冊的方法’’’if name is None: name = function.__name__self.funs[name] = function
至此,Client端和Server端都寫好了。
測試:
以上就是python實現一個簡單RPC框架的示例的詳細內容,更多關于python 實現RPC框架的資料請關注好吧啦網其它相關文章!
相關文章:
1. Django中的AutoField字段使用2. Django ORM實現按天獲取數據去重求和例子3. 解決docker與vmware的沖突問題4. IntelliJ Idea 2020.1 正式發布,官方支持中文(必看)5. IntelliJ IDEA設置自動提示功能快捷鍵的方法6. asp.net core應用docke部署到centos7的全過程7. Java 3D的動畫展示(Part1-使用JMF)8. Python基于jieba, wordcloud庫生成中文詞云9. 如何在vue3.0+中使用tinymce及實現多圖上傳文件上傳公式編輯功能10. 刪除docker里建立容器的操作方法
