为什么我们要使用protobuf ?

接口联调中常见的问题

最近写接口,和客户端联调比较多,发现了以下几点问题:

  1. 接口返回 [ ]{ } 的问题
    比如正常返回是一个对象,但是如果是空的话,返回的是空数组,此时客户端让我们改为空对象。
    这其实是php本身如此。

  2. 数值 or 字符串?
    因为php是弱类型的,有时候会返回字符串类型的数值(如: 1 , '1')。此时客户端会让我们传指定的数值类型。

  3. 服务端定好的返回的数据结构,客户端不满足,会让我们调整结构。
    比如某个显示,有三个条件满足才显示,此时客户端希望我们提供一个字段控制其显示如否即可。

  4. 写接口文档
    开发者其实都不愿意写文档,我们写好后,后期改了,可能也会忘记调整文档。

以上就是一些常见的问题了。我发现如果使用 protobuf ,可以解决上述问题。
我们来看下 protobuf 的一些优点吧。

使用 protobuf 的优点

  1. protobuf 是基于二进制传输的,所以他比json更安全。并且同样的数据,因为 protobuf 不需要字段名称。传输量更小,省带宽,性能好。

  2. protobuf 传输数据前,是需要根据我们定好的格式,效验数据类型和数据结构的,所以如果数据类型不对,或者少字段,则在传输到客户端前,就截断了,并告诉后端是什么原因。这样就解决了上面的 1,2问题

  3. protobuf 是可以双方协作定好接口返回结构的,避免了上述的 问题3

  4. 写 protobuf 时,可以顺手把字段的注释加上,省掉了写接口文档的烦恼。

给大家看一个 protobuf 文件的示例

syntax = "proto3";
package proto.club;
/*xx请求*/
message ClubListReq {
    base.ReqCode      cmd        = 1;
    base.ExtReq       ext        = 2;
    uint32            page       = 3; // 页码
    optional string   keyword    = 4; // 搜索关键字,可选
}
/*xx返回*/
message ClubListRsp {
    base.RspCode        cmd       = 1;
    base.ExtRsp         ext       = 2;
    uint32              page      = 3;
    uint32              totalPage = 4;
    repeated   ClubInfo clubList  = 5; // 家族列表 [{}, {}, ...]
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
六月的风
Junwind
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 8

服务端用 PHP 实现么?

4个月前 评论
Junwind (楼主) 4个月前

增加复杂度,json就好了嘛

4个月前 评论
Junwind (楼主) 4个月前
梦想星辰大海

数据库的model转protobuf的对象,这个过程有点费人。

4个月前 评论

不是搞游戏这种没必要

4个月前 评论
Buffett-Cai

感觉你好卑微,现在遇到的还是前后端交互的日常问题,客户端让你改啥就改啥,主要原因是没有事先定义好接口数据格式,还不爱写文档,那用什么传输都会存在这种问题,因为传输只管你的数据,不管你的定义,只不过强类型的序列化帮你事先校验了一遍格式类型而已。开发中应该是后端主导接口的设计,而不是前端指导后端开展工作,当然了如果前端的工作比后端的高很多那就另说。踩过坑的才会知道后端就应该提供一个字段控制客户端的显示,切勿在前端判断一大堆条件,也不要给个状态status=0然后让前端判断状态显示写死的文案,而应该后端加一个status_text之类的翻译好的文案给前端显示。设计接口表面上看很简单,实际细节可多了,线上版本的迭代都得考虑旧版本的兼容,光这一点都够折腾了,不能接口改动之后,旧版客户端全部崩溃,新版客户端才能用。也不能改个文案就让前端发个版本。不写文档注定只能一个人全栈干了哈,前端不可能去看你代码怎么定义的结构体

3个月前 评论
Junwind (楼主) 3个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!