grpc 和 protobuf - 当另一方未同步发布时如何处理新字段

grpc and protobuf - How to handle a new field when the other side is not releasing in sync

我遇到一种情况,grpc 通信的另一端与他们的发布不同步。因此,我的上司希望我添加一个字段,如果对方填写或不填写,该字段将在短时间内(如两周)起作用

我相信我可以通过将它添加到原型消息的末尾来做到这一点,这样其他字段的索引就不会改变。根据我用谷歌搜索的内容,可选字段在 3.15 版之前不可用,因此我必须使用变通方法。

向我描述的解决方法是使用 oneof。但是,我不是 100% 确定那是什么样子。所有示例都单独显示了 oneof 字段。属于其中一个值的索引是否与属于消息其余部分的索引相对应?

message TestMessage {  
    string somefield = 1;
    int someotherfield = 2;
    oneof mynewoptionalfield
    {
        string mynewfield = ???? Does this have to be 3 or is it 1?
        int ifihadanother = ???? Does this need to be 4 or 2?
    } 
}

问题:

您的用例正是 protobuf 旨在处理的。您需要做的就是:在消息中添加一个新字段。在最简单的情况下,客户端应用程序代码在服务器推出完成之前根本不会查看新字段,因此有时不会注意到它存在有时会丢​​失。

你说得对,你不应该更改预先存在的字段的索引(字段 ID)。尽管我会注意到您可以在消息中的任何地方 添加新字段;字段的写入顺序对 protobuf 无关紧要。

所以您只需添加另一个字段,例如:

message TestMessage {  
    string somefield = 1;
    int someotherfield = 2;
    string mynewfield = 3;
}

没有使用3作为ID。您可以使用 4、10 或 10000。但是小数字对于 protobuf 更有效,通常只选择“下一个”id。 On-the-wire protobuf 使用 id 来标识字段,因此以后不要更改 id 很重要。

在 protobuf 3 中,所有字段在 protobuf 2 意义上都是“可选的”;没有“必填”字段。但是,protobuf 2 还为所有字段提供了“字段存在”。 Protobuf 3 只为 oneofs 和消息提供字段存在......直到最近重新引入“可选”关键字。

在 protobuf 3 中,如果您调用 textMessage.getMynewfield(),它将 始终 return 一个非空字符串。如果未发送字符串,它将使用空字符串 ("")。对于整数 0 是 returned,对于消息,“默认消息”(所有默认值)是 returned。这对于许多用例来说已经足够了,对你来说可能就足够了。

但是假设您需要区分 ""<notsent>。这就是现场存在所提供的。 protobuf 3 中的 Messages 具有“具有”方法 return true 如果存在值。但是原语没有那个存在信息。一种选择是用 standard wrappers 将原语“装箱”,使原语成为一条消息。较新版本的 protobuf 中可用的另一个选项是 optional 关键字。这两个选项都将提供类似 textMessage.hasMynewfield().

的方法
message TestMessage {  
    string somefield = 1;
    int someotherfield = 2;
    google.protobuf.StringValue mynewfield = 3;
    // -or-
    optional string mynewfield = 3;
}