如何用Python构建一个基础的RPC框架示例?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1121个文字,预计阅读时间需要5分钟。
原文:本文字需要一点Python+socket基础。回BERPC+客户端(Client):服务调用方。客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据打包成网络消息,再通过网络传输。
改写后:需掌握Python socket基础。了解RPC+客户端(Client):负责服务调用。客户端存根(Client Stub):存储服务端地址,封装客户端请求参数为网络消息,并通过网络发送。
本文需要一点Python socket基础。
回顾RPC
- 客户端(Client):服务调用方。
- 客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端。
- 服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理。
- 服务端(Server):服务的真正提供者。
- Network Service:底层传输,可以是 TCP 或 HTTP。
实现jsonrpc
在实现前,简单理一下整体思路。
1、Network Service 直接使用Python Socket相关的API实现 2.传输数据使用JSON,在Socket层会被压成二进制,我们无需关心。
模仿xmlrpc,Client与Server都采用Minix多继承机制来实现,每个类负责自身的事情,最终暴露出现的只有一个类中有限的方法。
先从Client端开始实现。
#client.py importrpcclient 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.py classRPCClient(TCPClient,RPCStub): pass
其中TCPClient负责通过Socket实现TCP链接并将数据请求过去,而RPCStub类主要将Client端调用Server端方法的相关信息打包,然后调用TCPClient类中的方法发送则可,两个类同样实现在rpclient.py文件中,代码如下。
classTCPClient(object): def__init__(self): self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) defconnect(self,host,port): '''链接Server端''' self.sock.connect((host,port)) defsend(self,data): '''将数据发送到Server端''' self.sock.send(data) defrecv(self,length): '''接受Server端回传的数据''' returnself.sock.recv(length) classRPCStub(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)#接收方法执行后返回的结果 returndata 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 importrpcserver defadd(a,b,c=10): sum=a+b+c returnsum s=rpcserver.RPCServer() s.register_function(add)#注册方法 s.loop(5000)#传入要监听的端口
实例化rpcserver.RPCServer类,然后通过register_function方法将想被Client端调用的方法传入,随后调用loop方法,将要监听的端口传入,RPCServer类的实现如下。
#rpcserver.py classRPCServer(TCPServer,JSONRPC,RPCStub): def__init__(self): TCPServer.__init__(self) JSONRPC.__init__(self) RPCStub.__init__(self) defloop(self,port): #循环监听5000端口 self.bind_listen(port) print('Serverlisten5000...') whileTrue: self.accept_receive_close() defon_msg(self,data): returnself.call_method(data)
RPCServer继承自TCPServer、JSONRPC、RPCStub,这些类同样实现在rpcserver.py文件中并且给出了详细的注释,所以就详细解释了。
classTCPServer(object): def__init__(self): self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) defbind_listen(self,port): self.sock.bind(('0.0.0.0',port)) self.sock.listen(5) defaccept_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() classJSONRPC(object): def__init__(self): self.data=None deffrom_data(self,data): '''解析数据''' self.data=json.loads(data.decode('utf-8')) defcall_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} returnjson.dumps(data).encode('utf-8') classRPCStub(object): def__init__(self): self.funs={} defregister_function(self,function,name=None): '''Server端方法注册,Client端只可调用被注册的方法''' ifnameisNone: name=function.__name__ self.funs[name]=function
至此,Client端和Server端都写好了。
测试:
以上就是python实现一个简单RPC框架的示例的详细内容,更多关于python 实现RPC框架的资料请关注易盾网络其它相关文章!
本文共计1121个文字,预计阅读时间需要5分钟。
原文:本文字需要一点Python+socket基础。回BERPC+客户端(Client):服务调用方。客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据打包成网络消息,再通过网络传输。
改写后:需掌握Python socket基础。了解RPC+客户端(Client):负责服务调用。客户端存根(Client Stub):存储服务端地址,封装客户端请求参数为网络消息,并通过网络发送。
本文需要一点Python socket基础。
回顾RPC
- 客户端(Client):服务调用方。
- 客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端。
- 服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理。
- 服务端(Server):服务的真正提供者。
- Network Service:底层传输,可以是 TCP 或 HTTP。
实现jsonrpc
在实现前,简单理一下整体思路。
1、Network Service 直接使用Python Socket相关的API实现 2.传输数据使用JSON,在Socket层会被压成二进制,我们无需关心。
模仿xmlrpc,Client与Server都采用Minix多继承机制来实现,每个类负责自身的事情,最终暴露出现的只有一个类中有限的方法。
先从Client端开始实现。
#client.py importrpcclient 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.py classRPCClient(TCPClient,RPCStub): pass
其中TCPClient负责通过Socket实现TCP链接并将数据请求过去,而RPCStub类主要将Client端调用Server端方法的相关信息打包,然后调用TCPClient类中的方法发送则可,两个类同样实现在rpclient.py文件中,代码如下。
classTCPClient(object): def__init__(self): self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) defconnect(self,host,port): '''链接Server端''' self.sock.connect((host,port)) defsend(self,data): '''将数据发送到Server端''' self.sock.send(data) defrecv(self,length): '''接受Server端回传的数据''' returnself.sock.recv(length) classRPCStub(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)#接收方法执行后返回的结果 returndata 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 importrpcserver defadd(a,b,c=10): sum=a+b+c returnsum s=rpcserver.RPCServer() s.register_function(add)#注册方法 s.loop(5000)#传入要监听的端口
实例化rpcserver.RPCServer类,然后通过register_function方法将想被Client端调用的方法传入,随后调用loop方法,将要监听的端口传入,RPCServer类的实现如下。
#rpcserver.py classRPCServer(TCPServer,JSONRPC,RPCStub): def__init__(self): TCPServer.__init__(self) JSONRPC.__init__(self) RPCStub.__init__(self) defloop(self,port): #循环监听5000端口 self.bind_listen(port) print('Serverlisten5000...') whileTrue: self.accept_receive_close() defon_msg(self,data): returnself.call_method(data)
RPCServer继承自TCPServer、JSONRPC、RPCStub,这些类同样实现在rpcserver.py文件中并且给出了详细的注释,所以就详细解释了。
classTCPServer(object): def__init__(self): self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) defbind_listen(self,port): self.sock.bind(('0.0.0.0',port)) self.sock.listen(5) defaccept_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() classJSONRPC(object): def__init__(self): self.data=None deffrom_data(self,data): '''解析数据''' self.data=json.loads(data.decode('utf-8')) defcall_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} returnjson.dumps(data).encode('utf-8') classRPCStub(object): def__init__(self): self.funs={} defregister_function(self,function,name=None): '''Server端方法注册,Client端只可调用被注册的方法''' ifnameisNone: name=function.__name__ self.funs[name]=function
至此,Client端和Server端都写好了。
测试:
以上就是python实现一个简单RPC框架的示例的详细内容,更多关于python 实现RPC框架的资料请关注易盾网络其它相关文章!

