protobuf 介绍,Python 和 Go 编写 rpc 服务(gRPC) (3)

通过上面的描述,我们已经了解 rpc 是什么以及它的整个流程,我们可以把 rpc 看成是一系列操作的集合。其中包含了很多对数据的操作,以及网络通信,但是有两个细节我们没有说。

1. 客户端存根和服务端存根要怎么生成

2. 序列化和反序列化使用的是什么数据协议(不是 json)

1. 动态代理技术:我们提到的 client stub  和 server stub,在具体的编码和开发实践中,都是通过动态代理技术自动生成的。

2. 序列化和反序列化:在 rpc 的调用过程中,我们可以看到数据需要在一台机器上传输到另外一台机器上。在互联网上,所有数据都是以字节的形式进行传输的,而我们在编程的过程中,往往都是使用数据对象。因此想要在网络上将数据对象和相关变量进行传输,就需要对数据对象进行序列化和反序列化操作。

序列化:把对象转换成字节序列的过程称为对象的序列化,也就是编码的过程

反序列化:把字节序列恢复成对象的过程称为对象的反序列化,也就是解码的过程

而序列化和反序列化也是要遵循相应的数据协议的,比如 json、xml,而 rpc 框架中使用更为广泛的是 Protobuf,这也是数据编解码的一种协议。

Protobuf(Google Protocol Buffers)是 Google 提供的一个语言无关、平台无关、可扩展的,用于序列化结构数据的工具库,它可用于(数据)通信协议、数据存储等。类似于 json,但是比 json 具有更高的转化效率,时间效率和空间效率都是 json 的 3 到 5 倍。并且具有跨语言性,支持:Python、Go、Java、C++、JavaScript 等等。

基于 xmlrpc 库实现一个 rpc

Python 实际上提供了一个内置的库叫做 xmlrpc,从名字上看也是基于 xml 实现的 rpc,也就是它的数据传输是通过 xml 实现的。

from xmlrpc.server import SimpleXMLRPCServer # 我们看到这里只需要编写业务逻辑,至于函数映射等逻辑是存根所做的事情 # 所以这和 web 服务是不一样的,并且也没有数据的编码和解码,客户端只需要专注于业务逻辑即可 class Vtuber: vtubers = ["神乐七奈", "夏色祭", "凑-阿库娅"] def show_vtubers(self): return self.vtubers def add_vtuber(self, vtuber): if vtuber not in self.vtubers: self.vtubers.append(vtuber) def remove_vtuber(self, vtuber): if vtuber in self.vtubers: self.vtubers.remove(vtuber) vtuber = Vtuber() # 调用 SimpleXMLRPCServer,绑定ip和端口 # 如果服务端某个函数返回了 None,那么需要指定 allow_none=True,否则客户端调用时会报错 server = SimpleXMLRPCServer(("localhost", 6666), allow_none=True) # 将实例对象注册给 rpc server server.register_instance(vtuber) server.serve_forever()

从代码来看,暴露出来的接口逻辑还是非常简单的,没有像 web 框架那样需要进行 url 的映射(Django 是 urlconfig、flask 是 route 等等),也不需要显示地进行数据的序列化和反序列化。那么下面来看看客户端的编写:

from xmlrpc import client # 这里只需要指定服务端的 ip 地址即可,通过 url 的方式 server = client.ServerProxy("http://localhost:6666") # 然后可以通过 server 直接调用里面的方法,非常的方便 print(server.show_vtubers()) # [\'神乐七奈\', \'夏色祭\', \'凑-阿库娅\'] server.add_vtuber("时雨羽衣") print(server.show_vtubers()) # [\'神乐七奈\', \'夏色祭\', \'凑-阿库娅\', \'时雨羽衣\'] server.remove_vtuber("凑-阿库娅") print(server.show_vtubers()) # [\'神乐七奈\', \'夏色祭\', \'时雨羽衣\']

从这里我们感觉似乎 xmlrpc 挺好用的,但如果你通过 web 框架也是同样可以做到 xmlrpc 的效果,只不过 web 框架的目的不在于此。而且 xmlrpc 还有一个局限性,就是客户端只能通过 xmlrpc 提供的客户端去访问,你像浏览器、requests 包都做不到,因为一个是 xml 协议、一个是 http 协议。而 web 框架是暴露出一个 url,可以支持不同的途径去访问,只要你能发送 http 请求即可。所以 web 框架更强调是灵活性,而 rpc 更强调的是本地调用效果,所以 rpc 更常在内部调用。

xmlrpc 库在数据的序列化和反序列化所使用的协议显然是 xml,而除了 xml 还有 json,只不过 Python 官方没有提供基于 json 进行序列化和反序列化的 rpc 库。

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

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