使用grpc时proto的一些问题

服务新版本更新后grpc接口报错did not read entire message

原因

原来是服务提供方的proto文件有修改,修改了一个接口的入参message结构,增加了一个参数,更新proto文件重新生成protobuf即可
然而,处理完后又有服务出现了新的错误grpc: error unmarshalling request: string field contains invalid UTF-8
如报错所示,字段类型定义与实际使用时的类型不对,再观察,居然是调整了message参数的序号,形如:

message B {
    int32 foo = 1;
    int32 bar = 2;
}

message A {
    ... 
    string arg5 = 5;
    repeated B arg6 = 6;
}

被改为了
···
message A {

string arg5 = 5;
string arg7 = 6;
repeated B arg6 = 7;
}
···
即修改且重复使用了字段的序号

解决方法

proto3的规范也是改来改去,来回横跳,具体还是要根据当前使用版本确定如何使用
比如 optionalv3.0.0时被移除,v3.12.0被重新引入但需要手动启用,同时v3.15.0时已经可以像proto2一样直接使用
为了确保proto文件能向前向后有较好的兼容性,proto文件要遵循一些基本规则:

  • 序号必需是唯一的,可以不连续,尽量是递增的
  • 禁止修改已有字段的序号
  • 尽量不使用 requireddefault(proto3已废弃,见参考链接)

同样,更新proto文件时同样有些主要事项注意:

  • 可以新增接口,但老系统无法响应
  • 可以新增字段,前提是已有字段序号不能改变
    • 老系统序列化后的数据可以被新格式解析,但需要自行处理缺省值
    • 老系统也可以解析新格式的序列号数据,但新增字段被丢弃
  • 字段可以被移除,但最好通过reserved字段标记序号被保留或给字段添加OBSOLETE_前缀进行标记
  • int32, uint32, int64, uint64 和 bool类型都是兼容的
  • string 和 bytes兼容,如果 bytes 是合法的UTF-8 bytes的话

参考链接

proto3 v3.0.0
proto3 v3.15.0
原文链接