微服务输入输出域模型
Microservice input and output domain models
我正在使用 Kafka 来解耦我的服务,但我对服务使用和产生输入和输出的方式有一些想法。
如果我有一个服务A,它从我无法控制的一些外部服务中获取数据,我被迫适应外部系统提供的数据格式(域)。按照这样的做法,我的服务 A 将其结果以自己的格式(域)推送到主题。
顺便说一下,我有一个服务 B,它与服务 A 做类似的事情,但使用一些其他外部服务,并且有自己的数据格式(域),它推送到一个单独的主题。
现在,A 和 B 产生的数据的语义相似,但不相同。但是,管道中的下一步是服务 C,它应该使用 A 和 B 产生的东西,用它做一些事情并吐出结果。
C 是否应该只知道如何从一个地方使用数据,这意味着 A 和 B(以及未来的任何其他)需要在特定于 C 的域中生成它们的输出?这意味着,如果 C 消费者改变了它的域,A、B 和任何其他生产者都必须改变,我不喜欢这样。另外,如果我添加另一个消费者,例如 D,这意味着 A 和 B,使用这个类比,应该知道 D 也是他们的消费者,这在我看来很可怕。
我认为 C 应该对其输入负责,这意味着它依赖于 A 和 B 模型(以及任何其他可能产生自己数据的模型)。
这也意味着,当添加新源时,必须更改 C 以包含该数据。
实际上,我倾向于 ManySources-OneSink 组件,而不是 OneSource-ManySinks。
有什么首选做法吗?
您的每项服务都应使用对其特定业务逻辑最有意义的数据格式。
为了整合目的:
Inbound channel adapters
- 在数据 进入 服务时将数据转换为所需格式。
Outbound channel adapters
- 在 退出 服务时将数据转换为所需格式。
更多信息: https://www.enterpriseintegrationpatterns.com/patterns/messaging/ChannelAdapter.html
在选择集成模式之前,需要在战略层面对业务子域、维护这些服务的团队、谁拥有什么、您期望模型如何发展等进行分析。
我建议您查看 Hohpe 和 Woolf 的 DDD book and then Enterprise Integration Patterns 的上下文映射部分以了解具体实现。
Are there any preferred practices?
消息规范。
也就是说,您可以将它们转换为消息格式 mA、mB 和 mC,而不是将 A、B 和 C 相互耦合。只要(mA、mB、mC)兼容,服务就可以相互通信。
实现此目的的一种方法是将 mA、mB 和 mC 限制为同一模式的不同“版本”,其中模式的演变受到限制
- 在初始版本之后可能不会添加新的必填字段
- 可选字段应具有默认值
- 消费者应忽略无法识别的字段
- 字段可以弃用,但绝不会重复使用(例如,参见 HTTP status code 306)
Greg Young 的书 Versioning in an Event Sourced System 专门用一章来阐述这个想法。如果您查看各种标准化的消息序列化(Avro、Protocol Buffers 等),您会看到类似的想法。
Should one service produce output on its own topic and make dependent services to consume from them, or vice versa, or some third option?
主要是管道——我们如何将消息从一个系统复制到另一个系统?
从概念上讲,您似乎希望 C 消费 A 和 B 产生的消息的逻辑 outer join。所以我想直接的问题是您目前是否有来自 A 和 B 的这些相同消息的消费者A 不想要来自 B 的消息,反之亦然。如果这是您所知道的唯一用例,那么将事情简化为一个主题可能会有好处。
你说的是上下文映射。 BC之间的关系。上游侧和下游侧。两个BC之间的关系不是你的选择来决定两者中哪个是上游哪个是下游。他们本身。您可以选择集成方式(使用 REST API、使用事件、同步、异步...)。您应该绘制上下文图,确定哪种战略模式适用于 BC 之间的每种关系,并决定如何实施它。
我正在使用 Kafka 来解耦我的服务,但我对服务使用和产生输入和输出的方式有一些想法。
如果我有一个服务A,它从我无法控制的一些外部服务中获取数据,我被迫适应外部系统提供的数据格式(域)。按照这样的做法,我的服务 A 将其结果以自己的格式(域)推送到主题。
顺便说一下,我有一个服务 B,它与服务 A 做类似的事情,但使用一些其他外部服务,并且有自己的数据格式(域),它推送到一个单独的主题。
现在,A 和 B 产生的数据的语义相似,但不相同。但是,管道中的下一步是服务 C,它应该使用 A 和 B 产生的东西,用它做一些事情并吐出结果。
C 是否应该只知道如何从一个地方使用数据,这意味着 A 和 B(以及未来的任何其他)需要在特定于 C 的域中生成它们的输出?这意味着,如果 C 消费者改变了它的域,A、B 和任何其他生产者都必须改变,我不喜欢这样。另外,如果我添加另一个消费者,例如 D,这意味着 A 和 B,使用这个类比,应该知道 D 也是他们的消费者,这在我看来很可怕。
我认为 C 应该对其输入负责,这意味着它依赖于 A 和 B 模型(以及任何其他可能产生自己数据的模型)。 这也意味着,当添加新源时,必须更改 C 以包含该数据。
实际上,我倾向于 ManySources-OneSink 组件,而不是 OneSource-ManySinks。
有什么首选做法吗?
您的每项服务都应使用对其特定业务逻辑最有意义的数据格式。
为了整合目的:
Inbound channel adapters
- 在数据 进入 服务时将数据转换为所需格式。Outbound channel adapters
- 在 退出 服务时将数据转换为所需格式。
更多信息: https://www.enterpriseintegrationpatterns.com/patterns/messaging/ChannelAdapter.html
在选择集成模式之前,需要在战略层面对业务子域、维护这些服务的团队、谁拥有什么、您期望模型如何发展等进行分析。
我建议您查看 Hohpe 和 Woolf 的 DDD book and then Enterprise Integration Patterns 的上下文映射部分以了解具体实现。
Are there any preferred practices?
消息规范。
也就是说,您可以将它们转换为消息格式 mA、mB 和 mC,而不是将 A、B 和 C 相互耦合。只要(mA、mB、mC)兼容,服务就可以相互通信。
实现此目的的一种方法是将 mA、mB 和 mC 限制为同一模式的不同“版本”,其中模式的演变受到限制
- 在初始版本之后可能不会添加新的必填字段
- 可选字段应具有默认值
- 消费者应忽略无法识别的字段
- 字段可以弃用,但绝不会重复使用(例如,参见 HTTP status code 306)
Greg Young 的书 Versioning in an Event Sourced System 专门用一章来阐述这个想法。如果您查看各种标准化的消息序列化(Avro、Protocol Buffers 等),您会看到类似的想法。
Should one service produce output on its own topic and make dependent services to consume from them, or vice versa, or some third option?
主要是管道——我们如何将消息从一个系统复制到另一个系统?
从概念上讲,您似乎希望 C 消费 A 和 B 产生的消息的逻辑 outer join。所以我想直接的问题是您目前是否有来自 A 和 B 的这些相同消息的消费者A 不想要来自 B 的消息,反之亦然。如果这是您所知道的唯一用例,那么将事情简化为一个主题可能会有好处。
你说的是上下文映射。 BC之间的关系。上游侧和下游侧。两个BC之间的关系不是你的选择来决定两者中哪个是上游哪个是下游。他们本身。您可以选择集成方式(使用 REST API、使用事件、同步、异步...)。您应该绘制上下文图,确定哪种战略模式适用于 BC 之间的每种关系,并决定如何实施它。