浅谈protobuf

1. protobuf是什么?

1.1 protobuf概述

protobuf是Google公司提出的一种轻便高效的结构化数据存储格式,常用于结构化数据的序列化,具有语言无关、平台无关、可扩展性特性,常用于通讯协议、服务端数据交换场景,github地址:https://github.com/protocolbuffers/protobuf

protobuf的核心内容包括:

  • 定义消息:消息的结构体,以message标识。
  • 定义接口:接口路径和参数,以service标识。

通过protobuf提供的机制,服务端与服务端之间只需要关注接口方法名(service)和参数(message)即可通信,而不需关注繁琐的链路协议和字段解析,极大降低了服务端的设计开发成本。

1.2 protobuf使用案例

假设有个服务端程序SSR,期望对外提供一个注册接口,调用方传入手机号姓名邮箱三个信息,其中邮箱是选填的,那通过protobuf如何来实现接口定义呢?

  • step1: 定义服务名SSR和方法名register
service SSR {
    rpc register(RegisterRequest) returns (RegisterResponse);
};
  • step2: 定义接口参数和约束
message RegisterRequest {
    required string name = 1; // 姓名
    required string tel = 2; // 手机号
    optional string email = 3; // 邮箱:可选
};
message RegisterResponse {
    required int code = 1; // 错误码
    optional string err_msg = 2; // 错误信息
};
  • step3: 使用protoc生成语言相关的协议代码
// for golang
protoc -I . -I /usr/local/include -I $(GOPATH)/src --go_out=. ssr.proto

// for cpp
protoc -I . -I /usr/local/include --cpp_out=. ssr.proto

利用官方提供的protoc生成语言无关的协议代码,比如golang、C++、python等等

  • step4:实现protobuf定义的接口
class SsrImpl : public proto::SSR {
    void register(::google::protobuf::RpcController* controller,
                    const proto::RegisterRequest* request,
                    proto::RegisterResponse* response,
                    ::google::protobuf::Closure* done);
}
  • step5:通过rpc框架注册Service & 实现业务逻辑
// 比如baidu-rpc框架为例
auto ssr = new baidu::rpc::Server();
ssr->AddService(new SsrImpl(), baidu::rpc::SERVER_DOESNT_OWN_SERVICE);

通过protobuf我们可以低成本的定义调用接口,并且无需关注繁琐的序列化过程,大大降低了服务端的开发设计成本。

1.3 protobuf延伸知识

为了支持复杂数据结构和实现对数据的种种约束,protobuf内置了自己的一套规则和语法,详细可以参考:https://developers.google.com/protocol-buffers/docs/overview

在一些特殊场景需求时,可以查阅protobuf开发者文档。

2. protobuf vs JSON vs flatbuf

数据交换除了使用protobuf外,还可以使用JSON、flatbuf等,这里简单介绍一下各自的优缺点和适用场景。

protobuf

  • 优势:
    • 类型安全
    • 易用性好
    • 序列化/反序列性能好
    • 兼容性好
    • 不仅可以定义结构体,还可以定义rpc服务接口
  • 劣势:
    • 可读性较差:没有schema的情况下,难以阅读和编辑。
    • 灵活性较差:无法动态修改schema。

jsonhttps://www.json.org/json-zh.html

  • 优势:
    • 可读性好:方便理解和编辑
    • 易用性好:使用简单
    • 灵活性好:支持动态修改schema
  • 劣势:
    • 序列化/反序列化性能差
    • 编码问题导致解析失败之类的

flatbufhttps://google.github.io/flatbuffers/

  • 优势:
    • 灵活性好
    • 性能好:序列化/反序列化几乎无耗时、高效的内存使用和读取速度。
    • 占用内存小
  • 劣势:
    • 可读性差
    • 易用性差:使用成本高,接口较为复杂

序列化/反序列化性能对比图:(来源于 https://codeburst.io/json-vs-protocol-buffers-vs-flatbuffers-a4247f8bda6f

各自的应用场景,可以参看图:

简单总结:

  1. rpc场景定义服务接口使用protobuf。(开发者友好 & 更好的性能)
  2. 高频序列化/反序列化场景 & 期望灵活schema则使用flatbuf。(灵活的schema & 更好的性能)
  3. 关注可读性&开发成本则使用JSON。(开发者友好 & 灵活的schema)

3. protobuf坑和小技巧

  1. 字符串如果包含非英文字符,建议使用bytes字段:https://developers.google.com/protocol-buffers/docs/proto#scalar
  2. 已有字段的field number不要修改:https://developers.google.com/protocol-buffers/docs/proto#assigning_field_numbers
  3. 慎用required字段,容易造成不兼容的隐患(既不能删,又不能加):https://stackoverflow.com/questions/31801257/why-required-and-optional-is-removed-in-protocol-buffers-3
  4. 路过的老哥,帮点个赞。。

浅谈protobuf - 知乎 (zhihu.com)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值