微服务输入和输出域模型

时间:2018-10-05 09:26:46

标签: dependencies domain-driven-design microservices kafka-topic

我正在使用Kafka分离服务,但是我对服务消费和产生输入输出的方式有一些想法。

如果我有一个服务A,该服务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。

有没有首选的做法?

4 个答案:

答案 0 :(得分:4)

您正在谈论的是上下文映射。 BC之间的关系。上游和下游。确定两个BC中的哪个是上游和下游,不是您选择两个BC之间的关系。他们本身。您可以选择集成方式(使用REST API,使用事件,同步,异步等)。您应该绘制一个上下文图,确定适用于BC之间每个关系的策略模式,并决定如何实现它。

答案 1 :(得分:2)

在选择集成模式之前,需要在战略层面上对业务子域,将维护这些服务的团队,谁拥有什么,您期望模型如何发展等进行分析。

我建议先看看DDD book的上下文映射部分,然后再看Hohpe和Woolf的Enterprise Integration Patterns进行具体实现。

答案 2 :(得分:1)

  

有没有首选的做法?

消息规范。

也就是说,您可以将它们分别设置为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,协议缓冲区等)时,您会看到类似的想法。

  

一种服务是否应该在其自己的主题上产生输出并让相关的服务从它们中消费,反之亦然,或者某些第三种选择?

通常,这很麻烦-我们如何从一个系统到另一个系统获取消息的副本?

从概念上讲,您似乎希望C消费A和B产生的消息的逻辑outer join。所以我想直接的问题是您当前是否拥有来自A的这些相同消息的使用者,不想从B收到消息,反之亦然。如果这是您所知道的唯一用例,那么将事情简化为一个主题可能会有好处。

答案 3 :(得分:0)

每个服务都应使用对其特定业务逻辑最有意义的数据格式。

出于集成目的:

  • Inbound channel adapters-在输入服务时将数据转换为所需的格式。
  • Outbound channel adapters-在退出服务时将数据转换为所需格式。

有关更多信息: https://www.enterpriseintegrationpatterns.com/patterns/messaging/ChannelAdapter.html