在proto定义中恢复被reserved标记的字段是否合规?
是否可以直接移除reserved复用原编号
分两种场景判断:
- 符合以下全部条件时可以直接复用:
- 你要恢复的字段类型、名称、业务含义和当初被删除、加入reserved的原字段完全一致
- 你确认该编号没有被其他任何同消息体的字段临时使用过
- 只要不满足上面的任意一个条件,就必须使用全新的未被占用过的字段编号,不能复用旧的预留编号。
不符合条件时复用预留编号的影响
如果在字段定义不匹配的情况下直接移除reserved复用旧编号,会导致严重的兼容性问题:
- 序列化/反序列化失败:旧版本服务生成的proto二进制数据中,该编号对应的值是旧字段的类型,新版本服务按照新字段类型解析时会直接报错,极端情况会引发服务崩溃
- 业务逻辑异常:如果新旧字段类型刚好兼容(比如都是string)但业务含义完全不同,旧数据会被新版本错误解析成新字段的值,产生脏数据,引发不可预期的业务错误
- 上下游服务兼容性故障:未升级的下游服务会把新字段的值按照旧字段的定义解析,同样会触发上述问题
示例修改方案
你给出的场景中要恢复的就是原本编号为2的string manufacturer字段,和当初预留的编号对应的原字段完全一致,直接移除reserved、取消注释即可,修改后定义如下:
message ProductDetail { string name = 1; string manufacturer = 2; }
该修改不会产生兼容性问题,新旧版本服务都可以正常解析该字段。
内容的提问来源于stack exchange,提问作者Daniel Arechiga
相关产品推荐
相关产品推荐

