为了兼容新业务,把 proto2 里的 required string mobile 改成了 optional。新服务发的消息不带这个字段,没升级的旧客户端立刻报 Message missing required fields: mobile,整条消息解析失败。乍看像缓存或者权限的锅,追下去往往不是。

protoc --descriptor_set_out=old.desc old.proto
protoc --decode=Order --descriptor_set_in=old.desc order.bin

追下去是这么回事:required 的校验在读取端做,写端不写这个字段,旧代码的解析器就认为报文不完整。protobuf 官方早就建议不要用 required,原因就是它没法做向前兼容。

碰到「Protobuf required 兼容」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。

线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。

具体做法是,先把 required 全部改成 optional 但保留字段编号和类型;读取端自己补一层业务校验 缺字段时给默认值或明确报错;确认所有消费方都升级完 再把校验收严;发布前用旧版本二进制解析一条新报文 验证不抛异常。

验收就看一点,旧客户端解析新报文不再抛 missing required fields 缺字段走业务默认值。

作者 9823189