记录一个protobuf枚举类型引发问题的分析和思考

背景:

  项目使用protobuf作为socket传输数据的序列化协议 数据对象的定义时 使用了很多枚举类型

人物:

  这部分代码经手应该超过3位以上程序员

起因:

  为了丰富聊天内容形态 增加了新的消息类型(嫌原单图展示死板 增加了多图合并展示的消息类型)

经过:

  正常的开发、提测, dang!!发现老版本在进入聊天界面时会必先崩溃 排查发现原因

  protobuf 对象生成的java对应的代码中 旧版本不认识新版本数据 导致枚举类型的值为 UNRECOGNIZED(-1)

  旧代码中通过getNumber()获取对应值的时候直接抛出异常(方法定义中并没有声明) IllegalArgumentException("Can't get the number of an unknown enum value.");

结果:

  很明显 旧版本不能兼容新加的类型

解决:

  其实很多方法可以解决这个问题

  其中比较理想的是

    如果项目之前引入热修复的话 这里打个补丁 改一下代码(可惜没如果)

    服务器端增加客户端版本判定 将新类型转成旧类型处理 不过 如果处理不当可能造成丢图(没办法对我们来说这是最好的结果了)

  还有相对不理想的

    比如先给旧版本来一个小升级 解决这个问题(要等用户大量升级小版本之后才能上最新版本 周期比较长)

    旧版本强制升级(会造成一定量的用户流失)

思考:

  其实这个问题很好排查也很好解决 但是却能留给我一些思考 

  1 如果protobuf生成的代码 能将抛出的异常写在方法声明里 其实就可以提醒调用者注意这个部分的问题

  2 如果当初写这个对象转换逻辑的人 在获取枚举对应值的时候发现生成代码的问题 使用get*Value()而不是get*().getNumber()

  3 早点引入热修复也是 

  4 如果项目组定期组织代码review 也许也能发现问题

记:

即便是大公司 较成熟的协议 使用起来也可能存在隐患

掉过越多坑的程序员 越有价值

早为未来做打算

闲暇时间多翻翻之前的(无论是谁写的)代码 即便是互相挑刺 对项目来讲 是好事情

猜你喜欢

转载自www.cnblogs.com/waterbear/p/10740630.html