Protobuf 3打破了合同可加性

时间:2016-12-07 18:04:24

标签: grpc protocol-buffers proto3 grpc-java

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

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

想象一下,我有服务A 以及 B队所拥有的一对消费者服务 B C strong> C队。

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

然后, B队更新他们的服务,使用更新的合同进行通话并传递“真实”'作为字段值。 然后, Team C 仍然使用旧合同并调用相同的服务 - 值被替换为false。 C队并不意味着它,而且他们根本不了解这个领域。

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

在Thrift中,这样的事情只需通过一次检查(.isSet())完成。

有像对象wrapping这样的原始数据的肮脏变通方法,但它强制使用特定于库实现的引用检查(至少在java中),这似乎是比强大的解决方案更糟糕的黑客攻击。而且,最终,我必须将所有内容包装在包装器中,正如您想象的那样,它也不是很好的解决方案。

您在2017年使用Protobuf 3管理此类情况的最佳做法是什么?您如何管理/协调团队/服务之间的合同更新?感谢

注意:这个问题并不完全是关于如何实现对未设置/缺失值的检测缺失,而是关于如何使用它和{{ 3}}

2 个答案:

答案 0 :(得分:2)

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

举个例子,假设你正在添加一个可以启用或禁用的新功能。执行此操作的正确方法是在名为enable_new_feature的请求消息中添加bool字段。由于较旧的客户端不了解此字段,因此他们的请求将默认为false,因此他们会获得他们期望的旧行为。添加disable_new_feature字段可能是错误的方法,因为那样你确实会通过启用他们不想要的东西来打破旧客户端。

答案 1 :(得分:1)

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

相关问题