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?
}
}
问题:
- 我使用的索引是什么???分数是
- 当另一方不打算重新编译和部署对协议文件的更改时,这是正确的变通方法吗?
- 然后如何检查我的 C++ 代码中是否填写了该字段?
您的用例正是 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;
}
我遇到一种情况,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?
}
}
问题:
- 我使用的索引是什么???分数是
- 当另一方不打算重新编译和部署对协议文件的更改时,这是正确的变通方法吗?
- 然后如何检查我的 C++ 代码中是否填写了该字段?
您的用例正是 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;
}