Protobuf 3 打破契约可加性
Protobuf 3 breaks contract additivity
我在分布式环境中使用 Protobuf 3 和 gRPC ("microservices")。
由于 Protobuf 3 中缺少支持 not-set/missing 值,我遇到了以下与合约可加性相关的问题。
假设我有 服务 A 和几个消费者服务 B 和 C 拥有B 队 和C 队。
如果我向服务 A 的合同添加一个字段,例如布尔值,首先它将具有默认值,该值将按原样写入数据库。
然后,B 队 更新他们的服务以使用更新的合同进行通话,并将 'true' 作为字段值传递。
然后,Team C 仍然使用旧合同并调用相同的服务 - 值被替换为 false。 但是C队不是那个意思,而且他们根本不知道那个领域
因此,服务 A 根本无法延长合同,因为由于各种原因未更新的消费者可能会损害数据,而服务 A 对此无能为力。
在 Thrift 中,这些事情只需通过一次检查即可完成 (.isSet()
)。
有一些肮脏的解决方法,例如 wrapping 原语到对象中,但它强制使用特定于库实现的引用检查(至少在 java 中),这似乎是相当糟糕的 hack比稳健的解决方案。此外,最终,我必须将所有内容都包装在包装器中,正如您想象的那样,这也不是很好的解决方案。
2017 年,您在 Protobuf 3 中使用哪些最佳实践来管理此类情况?您如何 manage/coordinate 在 teams/services 之间签订合同更新?谢谢
注意:这个问题不完全是关于如何实现对not-set/missing值的检测缺失,而是关于如何忍受这些以及 .
使用 oneof
看起来像是包装器的 better/cleaner 替代品。请参阅类似问题的答案:
我认为这里的问题是尝试以这种方式检查字段存在并不是协议缓冲区的惯用用法(甚至在 proto2 中也是如此)。听起来您正在尝试通过添加新字段而不是读取这些新字段来改进您的架构,除非您确定它们来自更新的客户端。惯用的方法是改为执行此操作:只要确保新字段的默认值是合理的,并在未明确设置时保持兼容的行为。然后不要尝试检查存在——只需阅读字段,老客户将获得良好的默认行为。
举个例子,假设您要添加一项可以启用或禁用的新功能。正确的做法是在您的请求消息中添加一个名为 enable_new_feature
的 bool 字段。由于老客户不知道这个字段,他们的请求将默认为 false,因此他们会得到他们期望的旧行为。添加一个 disable_new_feature
字段可能是 错误的 方法,因为那样的话你确实会通过启用他们不想要的东西来破坏老客户。
我在分布式环境中使用 Protobuf 3 和 gRPC ("microservices")。
由于 Protobuf 3 中缺少支持 not-set/missing 值,我遇到了以下与合约可加性相关的问题。
假设我有 服务 A 和几个消费者服务 B 和 C 拥有B 队 和C 队。
如果我向服务 A 的合同添加一个字段,例如布尔值,首先它将具有默认值,该值将按原样写入数据库。
然后,B 队 更新他们的服务以使用更新的合同进行通话,并将 'true' 作为字段值传递。 然后,Team C 仍然使用旧合同并调用相同的服务 - 值被替换为 false。 但是C队不是那个意思,而且他们根本不知道那个领域
因此,服务 A 根本无法延长合同,因为由于各种原因未更新的消费者可能会损害数据,而服务 A 对此无能为力。
在 Thrift 中,这些事情只需通过一次检查即可完成 (.isSet()
)。
有一些肮脏的解决方法,例如 wrapping 原语到对象中,但它强制使用特定于库实现的引用检查(至少在 java 中),这似乎是相当糟糕的 hack比稳健的解决方案。此外,最终,我必须将所有内容都包装在包装器中,正如您想象的那样,这也不是很好的解决方案。
2017 年,您在 Protobuf 3 中使用哪些最佳实践来管理此类情况?您如何 manage/coordinate 在 teams/services 之间签订合同更新?谢谢
注意:这个问题不完全是关于如何实现对not-set/missing值的检测缺失,而是关于如何忍受这些以及
使用 oneof
看起来像是包装器的 better/cleaner 替代品。请参阅类似问题的答案:
我认为这里的问题是尝试以这种方式检查字段存在并不是协议缓冲区的惯用用法(甚至在 proto2 中也是如此)。听起来您正在尝试通过添加新字段而不是读取这些新字段来改进您的架构,除非您确定它们来自更新的客户端。惯用的方法是改为执行此操作:只要确保新字段的默认值是合理的,并在未明确设置时保持兼容的行为。然后不要尝试检查存在——只需阅读字段,老客户将获得良好的默认行为。
举个例子,假设您要添加一项可以启用或禁用的新功能。正确的做法是在您的请求消息中添加一个名为 enable_new_feature
的 bool 字段。由于老客户不知道这个字段,他们的请求将默认为 false,因此他们会得到他们期望的旧行为。添加一个 disable_new_feature
字段可能是 错误的 方法,因为那样的话你确实会通过启用他们不想要的东西来破坏老客户。