python实现rpc框架_使用Python实现RPC框架

前言

本文将会使用Python实现一个最简单的RPC框架,玩具向,不具有实用意义,但可以让你清醒的理解RPC框架的几个组成部分,只是比看Python自带的xmlrpc清晰。

本文需要一点Python socket基础。

如果你对Python Socket基础方面的内容不是很熟悉,推荐阅读Real Python的「Socket Programming in Python (Guide)」

吐槽一下VSCode,在开发一些比较复杂的Python项目时,VSCode的debug功能让人感到蛋疼,询问了Windows下使用VSCode的同事,都没有这样的问题,不清楚VSCode对Mac的支持是否存在问题,还只是我单纯的不会用:(

本文代码比较简单,所以还是使用VSCode进行开发。那我们开始吧!

回顾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

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.py

class 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端都写好了,跑一下吧。

总结一下

通过上述代码,再次理解一下RPC中这几个重要的概念,理解的是不是深入了一下。

客户端(Client):服务调用方。

客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端。

服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理。

服务端(Server):服务的真正提供者。

Network Service:底层传输,可以是 TCP 或 HTTP。

开源的RPC框架肯定不是这么简单的,其中考虑了特别的边界条件以及各种优化,但RPC本身确是简单的。

结尾

最近一直在研究Docker,尝试通过Go来写一个玩具docker,后面弄出来,会分享一下Go与docker相关的内容。

下篇文章见,对了,有帮助的话,点「在看」或「赞赏」进行催更吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/486305.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php根据分类生成网址,PHP实现无限极分类生成分类树的方法

本文实例讲述了PHP实现无限极分类生成分类树的方法。分享给大家供大家参考,具体如下:现在的分类数据库设计基本都是:每一个分类有一个id主键字段,一个pid指向父类的id,这样便可实现无限级分类,取出的数据就…

张亚勤:新范式、新架构和新模态突破传统算力,推动物理世界走向数字化

本文转自联想创投近日,在联想创投2020 CEO年会上,清华大学讲席教授、智能产业研究院院长、美国艺术与科学院院士、百度前总裁张亚勤先生带来了《未来科技趋势展望》。张亚勤表示,数字化的3.0时期已经到来,数字化的范围已从内容、社…

python魔法函数和装饰器_python魔法方法、构造函数、序列与映射、迭代器、生成器...

在Python中,所有以__双下划线包起来的方法,都统称为"魔术方法"。比如我们接触最多的__init__,魔法方法也就是具有特殊功能的方法。构造函数构造函数不同于普通方法,将在对象创建后自动调用它们。也就是在对象创建完成后…

javascript读取php,PHP如何读取由JavaScript设置的Cookie

cookie在开发中使用的非常多,但如果是使用JavaScript设置cookie然后使用PHP读取出来如何实现呢?即PHP与JavaScript下Cookie的交互使用是否可行呢?// 读取JavaScript设置的cookieheader("Content-type: text/html; charsetutf-8");i…

pycharm 无法import PIL

ubuntu 16.04 pycharm 中使用PIL,pyhon3版本报错:no module 备注:系统已安装PIL,在终端可以import 成功 解决: pycharm中在File -> Settings ->Project ->Project Interpreter ->Packge -> &#xff0…

【华为出品】智能体白皮书2020(附全文下载)

来源 | 华为、IDC、中国信通院等微信编辑 | 邱峰、罗兵微信审核 | 张祥、吴斌、数字理政究院、中通协大数据分会IDC、中国信息化百人会、中国信息通信研究院、中国人工智能产业发展联盟与华为联合编撰的《智能体白皮书》指出,在第四次工业革命爆发前的历史拐点&…

python生成配置文件config_Python configparser模块封装及构造配置文件

1.configparser模块简介使用配置文件来灵活的配置一些参数是一件很常见的事情,配置文件的解析并不复杂,在python里更是如此,在官方发布的库中就包含有做这件事情的库,那就是configParserconfigParser解析的配置文件的格式比较象in…

吴恩达【深度学习工程师】 04.卷积神经网络 第四周特殊应用(2)神经风格转换...

该笔记介绍的是《卷积神经网络》系列第四周:特殊应用(2)神经风格转换 主要内容有: 1.神经风格转换 2.卷积网络隐藏单元可视化显示 3.神经风格转换代价函数 4.内容代价函数 5.风格代价函数 *6.数据从一维到三维的推广 神经风格转换 把C(conten…

php grepmatch,linux最快的文本搜索神器ripgrep(grep的最好代替者)

前言说到文本搜索工具,大家一定会知道 grep, 它是 linux 最有用并最常用的工具之一。但如果要再一个大的工程项目中搜索某个关键词,大家也一定知道它比较耗时。所以就有了很多替代工具,之前最出名的是 Ack,Ag而最近又有了新的替代…

蒲慕明:《大脑之美》序言,脑探索的起点

来源:神经现实本文经授权摘自《大脑之美》序言作者:蒲慕明现代神经科学起源于十九世纪末期;圣地亚哥拉蒙-卡哈尔(Santiago Ramn y)的神经解剖学研究和他提出的神经元理论是主要的起点。一百多年来,神经科学…

pycharm python 模板配置_pycharm设置python脚本模板

PyCharmPyCharm是一个有名的Python IDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制。此外,该IDE提供了一些高级功能,以…

slow log php,善用php-fpm的慢执行日志slow log,分析php性能问题

众所周知,mysql有slow query log,根据慢查询日志,我们可以知道那些sql语句有性能问题。作为mysql的好搭档,php也有这样的功能。如果你使用php-fpm来管理php的话,你可以通过如下选项开启。PHP 5.3.3 之前设置如下&#…

04-numpy-笔记-transpose

借鉴代码https://blog.csdn.net/xiongchengluo1129/article/details/79017142 吐槽一下CSDN的垃圾广告。。 这是转置,所以1维(向量)和2维(矩阵)的转置的意义很直观,就是数学上学的。 难的就是超过三维的张量…

量子信息技术研究现状与未来——郭光灿

来源: 中国科学杂志社量子信息技术是量子力学与信息科学融合的新兴交叉学科, 它的诞生标志着人类社会将从经典技术迈进到量子技术的新时代, 本文将阐述量子信息技术的研究现状与未来. 文中描绘了量子技术发展远景, 即筑建各种类型的量子网络, 包括量子云计算网络、分…

springboot需要tomcat服务器吗_嵌入式 Tomcat AJP 协议对 SpringBoot 应用的影响

前言2020 年 1 月 6 日,国家信息安全漏洞共享平台(CNVD)收录了由北京长亭科技有限公司发现并报送的 Apache Tomcat 文件包含漏洞。Tomcat AJP 协议由于存在实现缺陷导致相关参数可控,攻击者利用该漏洞可通过构造特定参数,读取服务器 webapp 下…

php session 前缀,PHP文件包含--session

利用条件:session文件路径已知,且其中内容部分可控。php的session文件的保存路径可以在phpinfo的session.save_path看到。session 的文件名格式为 sess_[phpsessid],而 sessionid 在发送的请求的 cookie 字段中也可以看到。实例:“…

第一阶段 03Java的基本数据类型

03Java的基本数据类型 程序 数据 逻辑 基本数据类型:4类8种 (1)整型类型 byte   1B   8位   -128到127 short   2B   16位  -2^15到(2^15)-1 int    4B  32位  -2^31到(2^31)-1 long   8B  64位  -2^63到(2^6…

大脑与数学——利用代数拓扑研究模拟大脑 第一部分

来源:遇见数学蓝脑计划(Blue Brain Project)是尝试利用分子层级的哺乳类脑部逆向工程建立一个电脑模拟脑。这里模拟并不仅是包括人工神经网络模型,也包括生物过程的真实神经元模型,和一个经验重建模型连接组。该计划希…

spring cloud每次修改必须重新打包_Java面试系列spring相关

Spring中的Bean是线程安全的吗?Spring 中的 bean 默认都是单例的,所有线程都共享一个单例实例Bean,因此是存在资源的竞争,是线程不安全的。但是spring中大部分bean都是在方法内部操作,例如:Controller、Ser…

day20 派生属性和方法,钻石继承

class Animal:人和狗都是动物,所以创造一个Animal基类def __init__(self, name, aggressivity, life_value):self.name name # 人和狗都有自己的昵称;self.aggressivity aggressivity # 人和狗都有自己的攻击力;self.life_value life_value # 人和狗都有自己的…