这几天遇到一个问题,客户端从服务器拉取一批视频信息,C/S之间使用protocol buffer格式协议,但是由于视频信息结构太大,有好几十个字段(包含字符串、repeated、嵌套……,后台为了对外部提供一个通用的接口,就填上了所有这些字段),导致客户端拉下去的包过大,8个原始视频信息就有6k+, 客户端测试压缩过后还有3k+, 考虑到app流量和接入层对包大小限制,并且客户端实际需要的字段只有少部分,在考虑和给app提供一个特有的协议和其他方案之间进行权衡,最后的方案是:由客户端决定需要哪些字段,客户端需要哪些字段,服务器就填上哪些字段返回给客户端。对应到这种方案就讨论出了两种做法:1.写一个大的switch-case,每个字段都判断要不要填;2.采用反射动态填充。第一种方案最简单,也最挫,以后每次需改协议这个接口的代码都要改动,而且需要关心协议内容;第二种方法通用,开发量大,以后每次协议改动只需要重新加载一次协议文件就可以了。
之前了解过pb的编解码原理,其实比较简单,当时就想到了可不可以直接从编码下手,服务器不需要关心协议变动,也不用实现反射等。具体方法是:还是设置协议中的所有的字段、序列化(pb编码),然后将序列化后的内容过滤,去掉那些不需要的字段对应的内容,只把那些需要的字段对应的二进制内容抠出来再拼接起来,即可。可行的原因是pb的编码方式比较简单(编解码参考protocol buffer 编解码),而且都是兼容老版本的。然后自己很快写了个demo,测试ok。
测试中使用的pb文件内容如下:
package test_protos;
message