万物互联之~RPC专栏

Code:https://github.com/lotapp/BaseCode/tree/master/python/6.net/6.rpc/

3.1.概念

RPC(Remote Procedure Call):分布式系统常见的一种通信方法(远程过程调用),通俗讲:可以一台计算机的程序调用另一台计算机的子程序(可以把它看成之前我们说的进程间通信,只不过这一次的进程不在同一台PC上了)

PS:RPC的设计思想是力图使远程调用中的通讯细节对于使用者透明,调用双方无需关心网络通讯的具体实现

引用一张网上的图:

1.rpc.png

和HTTP有点相似,你可以这样理解:

老版本的HTTP/1.0是短链接,而RPC是长连接进行通信

HTTP协议(header、body),RPC可以采取HTTP协议,也可以自定义二进制格式

后来HTTP/1.1支持了长连接(Connection:keep-alive),基本上和RPC差不多了

keep-alive一般都限制有最长时间,或者最多处理的请求数,而RPC是基于长连接的,基本上没有这个限制

后来谷歌直接基于HTTP/2.0建立了gRPC,它们之间的基本上也就差不多了

如果硬是要区分就是:HTTP-普通话RPC-方言的区别了

RPC高效而小众,HTTP效率没RPC高,但更通用

PS:RPC和HTTP调用不用经过中间件,而是端到端的直接数据交互

网络交互可以理解为基于Socket实现的(RPC、HTTP都是Socket的读写操作)

简单概括一下RPC的优缺点就是:

优点:

效率更高(可以自定义二进制格式)

发起RPC调用的一方,在编写代码时可忽略RPC的具体实现(跟编写本地函数调用一般

缺点:

通用性不如HTTP(方言普及程度肯定不如普通话),如果传输协议不是HTTP协议格式,调用双方就需要专门实现通信库

PS:HTTP更多是Client与Server的通讯;RPC更多是内部服务器间的通讯

3.2.引入

上面说这么多,可能还没有来个案例实在,我们看个案例:

本地调用sum()

def sum(a, b): """return a+b""" return a + b def main(): result = sum(1, 2) print(f"1+2={result}") if __name__ == "__main__": main()

输出:(这个大家都知道)

1+2=3 1.xmlrpc案例

官方文档:

https://docs.python.org/3/library/xmlrpc.client.html https://docs.python.org/3/library/xmlrpc.server.html

都说RPC用起来就像本地调用一样,那么用起来啥样呢?看个案例:

服务端:(CentOS7:192.168.36.123:50051)

from xmlrpc.server import SimpleXMLRPCServer def sum(a, b): """return a+b""" return a + b # PS:50051是gRPC默认端口 server = SimpleXMLRPCServer(('', 50051)) # 把函数注册到RPC服务器中 server.register_function(sum) print("Server启动ing,Port:50051") server.serve_forever()

客户端:(Win10:192.168.36.144

from xmlrpc.client import ServerProxy stub = ServerProxy("http://192.168.36.123:50051") result = stub.sum(1, 2) print(f"1+2={result}")

输出:(Client用起来是不是和本地差不多?就是通过代理访问了下RPCServer而已)

1+2=3

2.server.png

PS:CentOS服务器不是你绑定个端口就一定能访问的,如果不能记让防火墙开放对应的端口

这个之前在说MariaDB环境的时候有详细说:https://www.cnblogs.com/dotnetcrazy/p/9887708.html#_map4

# 添加 --permanent永久生效(没有此参数重启后失效) firewall-cmd --zone=public --add-port=80/tcp --permanent 2.ZeroRPC案例:

zeroRPC用起来和这个差不多,也简单举个例子吧:

把服务的某个方法注册到RPCServer中,供外部服务调用

import zerorpc class Test(object): def say_hi(self, name): return f"Hi,My Name is{name}" # 注册一个Test的实例 server = zerorpc.Server(Test()) server.bind("tcp://0.0.0.0:50051") server.run()

调用服务端代码

import zerorpc client = zerorpc.Client("tcp://192.168.36.123:50051") result = client.say_hi("RPC") print(result) 3.3.简单版自定义RPC

看了上面的引入案例,是不是感觉RPC不过如此?NoNoNo,要是真这么简单也就谈不上RPC架构了,上面两个是最简单的RPC服务了,可以这么说:生产环境基本上用不到,只能当案例练习罢了,对Python来说,最常用的RPC就两个gRPC and Thrift

PS:国产最出名的是Dubbo and Tars,Net最常用的是gRPC、Thrift、Surging

1.RPC服务的流程

要自己实现一个RPC Server那么就得了解整个流程了:

Client(调用者)以本地调用的方式发起调用

通过RPC服务进行远程过程调用(RPC的目标就是要把这些步骤都封装起来,让使用者感觉不到这个过程)

客户端的RPC Proxy组件收到调用后,负责将被调用的方法名、参数等打包编码成自定义的协议

客户端的RPC Proxy组件在打包完成后通过网络把数据包发送给RPC Server

服务端的RPC Proxy组件把通过网络接收到的数据包按照相应格式进行拆包解码,获取方法名和参数

服务端的RPC Proxy组件根据方法名和参数进行本地调用

RPC Server(被调用者)本地执行后将结果返回给服务端的RPC Proxy

服务端的RPC Proxy组件将返回值打包编码成自定义的协议数据包,并通过网络发送给客户端的RPC Proxy组件

客户端的RPC Proxy组件收到数据包后,进行拆包解码,把数据返回给Client

Client(调用者)得到本次RPC调用的返回结果

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyydfw.html