1

我在分布式环境(“微服务”)中使用 Protobuf 3 和 gRPC。

由于 Protobuf 3 中缺乏支持的未设置/缺失值,我遇到了以下与合同可加性相关的问题。

想象一下,我有服务 A以及Team BTeam C拥有的几个消费者服务B和C 。

如果我向服务 A 的合同添加一个字段,例如布尔值,首先它将具有默认值,该值将按原样写入数据库。

然后,团队 B更新他们的服务以使用更新的合同进行对话,并将“true”作为字段值传递。然后,团队 C仍然使用旧合同并调用相同的服务 - 值被替换为 false。C队不是这个意思,而且他们根本不知道那个领域。

因此,服务 A 根本无法延长合同,因为由于各种原因没有更新的消费者仍然能够损害数据,而服务 A 对此无能为力。

在 Thrift 中,此类事情只需通过单次检查 ( .isSet()) 即可完成。

有一些肮脏的解决方法,比如将原语包装到对象中,但它强制使用特定于库实现的按引用检查(至少在 java 中),这似乎比健壮的解决方案更糟糕。此外,最终,我必须将所有内容包装在包装器中,正如您想象的那样,这也不是很好的解决方案。

2017 年,您在 Protobuf 3 中使用哪些最佳实践来管理此类情况?您如何管理/协调团队/服务之间的合同更新?谢谢

注意:这个问题不完全是关于如何对未设置/缺失值实施不检测,而是关于如何忍受它并遵循 Protobuf 3 哲学

4

2 回答 2

2

我认为这里的问题是尝试以这种方式检查字段的存在并不是真正习惯使用协议缓冲区(甚至在 proto2 中也没有)。听起来您正在尝试通过添加新字段而不是读取这些新字段来改进架构,除非您确定它们来自更新的客户端。惯用的方法是这样做:只要确保新字段的默认值是合理的,并在未明确设置时保持兼容的行为。然后不要尝试检查是否存在 - 只需阅读字段,旧客户端将获得良好的默认行为。

举个例子,假设您要添加一个可以启用或禁用的新功能。正确的方法是在您的请求消息中添加一个名为enable_new_feature. 由于老客户不知道这个字段,他们的请求将默认设置为 false,因此他们得到了他们期望的旧行为。相反,添加一个disable_new_feature字段可能是错误的方法,因为那样你确实会通过启用他们不想要的东西来破坏老客户。

于 2016-12-08T17:13:46.803 回答
1

使用oneof看起来像是包装器的更好/更清洁的替代品。请参阅类似问题的答案:https ://stackoverflow.com/a/40552570/618259

于 2016-12-07T18:37:18.037 回答