如何在微服务之间最好地共享和存储类似枚举的数据?

chr*_*low 9 java enums microservices

情况:微服务架构具有:

  • 微服务是用 Java 编写的,带有 Spring Boot 和 Hibernate
  • 一个选项服务,它通过 REST 接口提供有关Option的信息
  • 可以如下建模的选项数据,例如通过枚举(代表)
    • 有一些属性,比如enabled与之关联的状态。将来不太可能添加更多属于Option 的属性,这些属性必须与其直接绑定。
    • 很少需要添加新的OptionOptionType。它们永远不会被删除(如果需要,只是禁用)。
    • 一个选项应该有一个可以被引用的唯一标识符
    • 如果可能,应该没有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;
    }
}

Run Code Online (Sandbox Code Playgroud)
  • 其他微服务(目前有 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
}
Run Code Online (Sandbox Code Playgroud)

在我看来,在微服务之间存储和共享此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数据的最佳方式是什么?什么是最佳实践?

小智 5

虽然枚举在大多数编程语言中非常有用,但它们可能成为服务间通信的噩梦。如果您在微服务端点中使用枚举,它将成为 API 规范的一部分。一方面改变它们会导致另一方面的序列化/反序列化问题。所以你应该只在你的 API 中使用枚举,如果

  • 你肯定他们永远不会改变(例如工作日)或
  • 您是所有参与服务的代码的所有者,并且能够安排一次大爆炸式的重新部署。

在这些情况下,您可以在您的服务之间创建一个共享库。

如果这不适用,让您的生活更轻松,并将大多数类似枚举的数据(例如货币代码、国家/地区代码)视为可能会更改的简单字符串值。如果您想对这些值进行集中管理,为什么不为其创建一个充当主节点的微服务?这就是微服务架构的目的。提供一些其他服务可以不时查询的端点。为此,您甚至不需要持久层。


小智 0

第一个选项:

定义或创建新的模块/微服务/项目,仅包含 CommonMessage 、字符串消息、枚举、异常或使用 spring-boot 的多个微服务通用且可重用的所有内容。

但这些枚举没有参数化,因此您无法创建更新或删除。

您可以出于多种目的创建 Option ENUM 类,并且可以从 POM.xml 中注入这些类作为依赖项。

第二个选项:将其作为实体对象存储在数据库中,以便您可以管理这些数据。如果您想在其他微服务上使用这些数据,请不要忘记将此工件用作 POM.xml 中的依赖项,以便其他微服务可以调用您的服务或存储库。