一、概念
Protocol Buffers(简称ProtoBuf)是一种用于序列化结构化数据的开源数据交换格式。它由Google开发并于2008年开源发布。ProtoBuf是一种轻量级、高效、可扩展的方法,用于在不同系统之间传输和存储数据。以下是ProtoBuf的一些主要优势:
1.高效的序列化和反序列化
ProtoBuf采用二进制编码,相比XML和JSON等文本格式,它的序列化和反序列化速度更快,生成的数据体积更小。这使得它在网络传输和磁盘存储方面表现出色。
2.跨语言支持
ProtoBuf定义数据结构的方式独立于编程语言,因此可以在不同的编程语言之间轻松地共享数据。Google提供了多种语言的ProtoBuf库,包括C++、Java、Python等,还有社区维护的其他语言版本,截止目前共支持10种语言。
3.版本兼容性
ProtoBuf具有一定的向后兼容性,可以在不破坏现有数据结构的情况下扩展和修改数据格式。这对于长期维护和升级系统非常有用。
4.强类型
ProtoBuf是强类型的,数据结构在编译时定义,可以防止数据类型错误,提高了代码的稳定性。
5.可读性和可维护性
尽管ProtoBuf的二进制编码不像XML和JSON那样易于人类阅读,但ProtoBuf的定义是文本格式的,易于理解和维护。
举例:XML与proto格式
我们可以举出例子对这两者进行比较。
XML格式:
<person>
<name>John Doe</name>
<email>jdoe@</email>
</person>
Protocol buffers格式:
message person { name: "John Doe" ; email: "jdoe@"}
6.效率和性能
ProtoBuf的编解码器通常比使用文本格式的编解码器更快,这对于需要处理大量数据的应用程序来说尤其重要。
7.自动生成的代码
ProtoBuf定义文件可以用来生成相应编程语言的数据访问类,这简化了数据的操作。
8.紧凑性
由于二进制编码,ProtoBuf生成的数据通常比JSON和XML更紧凑,占用更少的存储空间。
总之,ProtoBuf是一种强大的数据序列化格式,适用于需要高效、跨语言、版本兼容性和可维护性的数据交换的应用程序。它在许多领域,特别是分布式系统和网络通信中,都有广泛的应用。
二、Protobuf的工作流
protobuf有两个版本,分别是proto2和proto3,后面我们学习的时候使用的都是新版的proto3,如果你后续在查找资料时发现不相同的地方,一定要确认下是哪个版本。
1. 定义.proto文件
首先你入要在.ptoto文件中定义你想要传输的数据结构。.proto文件很简单:使用message来定义每一个需要序列化的数据结构,每个message里面可以定义类型和名称。
2. 编译.proto文件
使用protobuf提供的编译工具,将.proto文件编译为对应开发语言的数据结构代码。
3. 在代码中序列化和解析
在代码中将数据结构序列化成字节数组发送出去,或者将接收到的字节数组反序列化成内存中的数据。
三、FastAPI实战雏形
注:当前FastAPI版本为0.111.0,合乎其要求的Python版本:3.8、3.9、3.10、3.11、3.12。
使用protobuf关键步骤如下:
- 在.proto文件中定义消息格式。
- 使用protobuf编译器。
- 使用Python协议缓冲区API来写入和读取消息。
1.基础准备
安装Python及FastAPI、Protobuf等包:
pip3 install fastapi
pip3 install uvicorn
pip3 install protobuf
2.配置protoc
去github下载对应和你PC对应版本的protoc:
最新版本的下载地址:https://github.com/protocolbuffers/protobuf/releases/tag/v26.1
3. .proto配置文件编写
syntax = "proto3";
message Response {
int32 code = 1;
message data {
string id = 1;
string title = 2;
}
repeated data dataList = 2;
}
message Request {
string channelId = 1; //频道id
int32 page = 2; //页码
int32 pageSize = 3; //页条目数
}
4. 使用protoc把配置文件转成python代码
protoc --python_out=. ./test.proto
注:protoc配置到环境变量!
然后当前目录下会生成与.proto文件名相似的python文件。
5 编写FastAPI服务端
import uvicorn
from fastapi import FastAPI, Form
from fastapi import Response as fres
from test_pb2 import Request, Response
app = FastAPI()
@app.post('/protobuf')
async def _protobuf(pyload: bytes = Form(...)):
# 解析请求
req = Request()
req.ParseFromString(pyload)
print(req)
# 编写响应
res = Response()
res.code = 200
d1 = res.data()
d1.id = "1"
d1.title = "小明"
d2 = res.data()
d2.id = "2"
d2.title = "李雷"
res.dataList.append(d1)
res.dataList.append(d2)
print(res.SerializeToString())
return fres(res.SerializeToString())
if __name__ == '__main__':
uvicorn.run(
app='main:app',
host="0.0.0.0",
port=8899,
workers=4,
reload=True,
debug=True)
四、参考资料
- https://github.com/protocolbuffers/protobuf?tab=readme-ov-file
- https://baike.baidu.com/item/Protocol%20Buffers/3997436?fr=ge_ala
- protobuf是什么?具有哪些优势?https://blog.csdn.net/zy1992As/article/details/132405232
- https://github.com/protocolbuffers/protobuf/tree/main/python
- Python环境下Protobuf使用教程,https://protobuf.dev/getting-started/pythontutorial/
- protobuf 详解,https://blog.csdn.net/wsnbb_2023/article/details/131608040?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-131608040-blog-132405232.235^v43^pc_blog_bottom_relevance_base8&spm=1001.2101.3001.4242.1&utm_relevant_index=1
- FastAPI实现Protobuf服务端,https://juejin.cn/post/7356942180386406454
- A Proxy service using FastAPI and Protocol Buffers (Proto3),https://github.com/g4lb/proxy-service
- Building a Proxy Service Application with FastAPI and Protocol Buffers (Proto3),https://ga1.medium.com/building-a-proxy-service-application-with-fastapi-and-protocol-buffers-proto3-a70aa102d39
- fastapi.tiangolo.com/,FastAPI官方网站