java如何在微服务之间最好地共享和存储类似枚举的数据?
情况: 具有以下功能的微服务体系结构:
- 微服务是用Java编写的,带有Spring引导和Hibernate
- 一种选项服务,通过REST接口提供有关选项的信息
- 选项可按如下方式建模的数据,例如通过枚举(代表性)
- 具有一些与之关联的属性,如
enabled
status。将来不太可能添加更多属于选项的属性,这些属性必须与之直接关联李> - 必须很少添加新的选项s和选项类型s。它们将永远不会被删除(如果需要,只需禁用)李>
- 选项应具有可引用的唯一标识符
- 如果可能的话,不应该有未知选项
- 具有一些与之关联的属性,如
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)需要能够访问选项数据。他们需要知道哪个选项存在,并以某种方式引用选项,例如通过其名称或标识符
- 其中一个服务(示例服务)需要在自己的REST接口中向外界提供选项数据类型作为过滤器设置。JSON中的filter对象如下所示:
{
"typeA": "TYPE_A_X1",
"typeB": "TYPE_B_Z2",
"typeC": [ "TYPE_C_U1", "TYPE_C_U2"]
// more filter settings
}
在我看来,在微服务之间存储和共享此选项数据的不同方法:
选项服务将选项数据存储在自己的数据库中。如果我将数据从数据库读取到Hibernate实体中,选项从那以后,在任何地方都只是一个
String
- 赞成者:
- 易于重命名、添加和删除选项s
- 反对:
- 在代码中使用选项时没有类型安全性,例如反序列化包含选项的响应时
- 示例服务无法在其OpenAPI文档中轻松提供选项数据(仅
String
) - 微服务需要查询和缓存来自选项服务的选项数据
- 赞成者:
选项数据仅存在于
enum
中的源代码中,如上面建模的,并通过lib在不同服务之间共享- 赞成者:
- 在需要选项的地方键入安全。在反序列化包含Options数据的响应时非常有用,但也可用于生成OpenAPI文档
- 微服务仍然可以通过其名称引用其数据库中的选项,因为它是唯一的
- 反对:
- 编辑选项的名称很困难
- 无法删除选项
- 如果添加了一个新的选项/OptionType,依赖该库的服务更新其库版本的顺序很重要。因为我们无法将响应反序列化为未知选项类型李>
- 赞成者:
还有一种可能是混合使用数据库和枚举解决方案,这有一个很大的缺点,即必须同时维护两个真实来源
在微服务之间存储和共享选项数据的最佳方式是什么?什么是最佳实践
# 1 楼答案
另一个选项:使用第一个选项,但要有专门的课程
Option
实例的有效性,则需要一个缓存了允许的Option
列表的服务示例代码:
# 2 楼答案
虽然枚举在大多数编程语言中非常有用,但它们可能会成为服务间通信的噩梦。 如果在微服务端点中使用枚举,它将成为API规范的一部分。在一侧更改它们将导致在另一侧出现序列化/反序列化问题。 因此,只有在以下情况下,才应该在API中使用枚举:
在这些情况下,您可以在服务之间创建一个共享库
如果不适用,让您的生活更轻松,并将大多数EnUM类数据(例如货币代码、国家代码)视为可更改的简单字符串值。如果您想对这些价值进行集中管理,为什么不为其创建一个充当主服务器的微服务呢?这就是微服务架构的用途。提供其他服务可以不时查询的一些端点。你甚至不需要一个持久层
# 3 楼答案
第一种选择:
定义或创建新的模块/微服务/项目,该模块/微服务/项目仅包含CommonMessage、String Message、Enum、Exception或所有通用的、可用于使用spring boot的多个微服务的可重用的内容
但这些枚举没有参数化,因此无法创建更新或删除
您可以创建用于多种用途的选项ENUM类,并且可以从POM注入这些类。xml作为一种依赖关系
第二种选择: 将其作为实体对象存储在数据库中,以便管理这些数据。 如果你想在其他微服务上使用这些数据,别忘了在POM中使用这个工件作为依赖项。xml,以便其他微服务可以调用您的服务或存储库