如何在微服务之间最好地共享和存储类似枚举的数据?
情况:微服务架构具有:
- 微服务是用 Java 编写的,带有 Spring Boot 和 Hibernate
- 一个选项服务,它通过 REST 接口提供有关Option的信息
- 可以如下建模的选项数据,例如通过枚举(代表)
- 有一些属性,比如
enabled与之关联的状态。将来不太可能添加更多属于Option 的属性,这些属性必须与其直接绑定。 - 很少需要添加新的Option和OptionType。它们永远不会被删除(如果需要,只是禁用)。
- 一个选项应该有一个可以被引用的唯一标识符
- 如果可能,应该没有UNKOWN选项
- 有一些属性,比如
enum OptionType {
TYPE_A,
TYPE_B,
TYPE_C;
}
enum Option {
TYPE_A_X1(TYPE_A),
TYPE_A_X2(TYPE_A),
TYPE_B_Z1(TYPE_B, false),
TYPE_B_Z2(TYPE_B);
TYPE_C_U1(TYPE_C);
TYPE_C_U2(TYPE_C);
TYPE_C_U3(TYPE_C);
private final OptionType type;
private final boolean enabled;
Option(OptionType type){
this.type = type;
this.enabled = true;
}
Option(OptionType type, boolean enabled){
this.type = type;
this.enabled = enabled;
}
}
- 其他微服务(目前有 3 个)需要能够访问Option数据。他们需要知道存在哪些Option并以某种方式引用一个Option例如通过其名称或标识符
- 其中一项服务 ( example-service ) 需要在其自己的 REST 接口中向外界提供Option数据类型作为过滤器设置。JSON 中的过滤器对象如下所示:
{
"typeA": "TYPE_A_X1",
"typeB": "TYPE_B_Z2",
"typeC": [ "TYPE_C_U1", "TYPE_C_U2"]
// more filter settings
}
在我看来,在微服务之间存储和共享此Option数据的不同方法:
- options-service将选项数据存储在自己的数据库中。如果我将数据库中的数据读入我的 Hibernate 实体中,则Option只是
String从那时起无处不在。- 亲:
- 易于重命名、添加和删除Option s
- 骗局:
- 在代码中使用Option时没有类型安全,例如在反序列化包含Option的响应时
- 示例服务无法在其 OpenAPI 文档中轻松提供选项数据(仅
Strings) - 微服务需要从options-service查询和缓存Option数据
- 亲:
- 选项数据仅存在于源代码中
enum,例如上面建模的,并通过库在不同的服务之间共享。- 亲:
- 在需要Option的任何地方输入安全。在反序列化包含Option数据的响应以及生成 OpenAPI 文档时非常有用
- 微服务仍然可以通过其名称引用其数据库中的选项,因为它是唯一的
- 骗局:
- 编辑选项的名称很困难
- 无法删除选项
- 如果添加了新的Option / OptionType,则依赖该 lib 的服务更新其 lib 版本的顺序很重要。由于我们无法将响应反序列化为UNKNOWN Option类型。
- 亲:
- 还存在混合数据库和枚举解决方案的可能性,这伴随着一个必须同时维护两个事实来源的大缺点。
在微服务之间存储和共享Option数据的最佳方式是什么?什么是最佳实践?
回答
虽然枚举在大多数编程语言中非常有用,但它们可能成为服务间通信的噩梦。如果您在微服务端点中使用枚举,它将成为 API 规范的一部分。一方面改变它们会导致另一方面的序列化/反序列化问题。所以你应该只在你的 API 中使用枚举,如果
- 你肯定他们永远不会改变(例如工作日)或
- 您是所有参与服务的代码的所有者,并且能够安排一次大爆炸式的重新部署。
在这些情况下,您可以在您的服务之间创建一个共享库。
如果这不适用,让您的生活更轻松,并将大多数类似枚举的数据(例如货币代码、国家/地区代码)视为可能会更改的简单字符串值。如果您想对这些值进行集中管理,为什么不为其创建一个充当主节点的微服务?这就是微服务架构的目的。提供一些其他服务可以不时查询的端点。为此,您甚至不需要持久层。