微服务架构中的耦合

时间:2018-07-01 10:11:20

标签: microservices coupling

在微服务体系结构中的应用程序上工作时,我偶然发现了与服务之间的耦合有关的问题。

这是订购产品的典型应用。拥有可以作为产品目录运行的服务似乎合情合理。我们的JavaScript客户端可以要求此服务提供可用的产品,然后在浏览器中显示它们。当用户单击产品时,我们必须创建一个订单。我们想管理其他服务中的订单。这样就创建了一个订单-这意味着用户X订购了产品Y。在技术层面上,我们只是将用户ID和产品ID保留在数据库中。

总而言之,我们有:

产品服务

产品类别:
产品ID,产品名称

订单服务

订单分类:
订单ID,产品ID,用户ID,订单日期

现在让我们想象一下以下情形-在JavaScript客户端中,我们希望列出用户订购的所有产品。订单服务提供给定用户的产品ID列表。但是用户关心的是产品名称,而不是ID。不幸的是,订单服务对产品名称一无所知。

我们可以通过以下几种方式解决此问题:

  • 仅假设客户端负责获取所需的信息。因此,在调用Orders服务并获取产品ID列表之后,它将再次调用Products服务,传递产品ID并获取相应的产品名称作为响应。然后,客户将这两个响应组合成有用的东西。这种方法可以使我们的服务保持干净,而不会将领域知识从一项服务泄漏到另一项服务。但这需要在客户端进行更多工作。

  • 订购服务在被要求订购产品时,将在后端调用产品服务。它检索产品名称,组合一个包含orderDate和productName的响应,并将其发送给客户端。客户要做的就是呈现数据。这种方法的缺点是,订单服务现在获得了比必需产品更多的产品知识。

  • “订单”服务中有关产品名称的重复信息。创建订单时,我们不仅传递产品ID,而且传递产品名称。这意味着Order类将如下所示: 订单类别:
    订单ID,产品ID,产品名称,用户ID,订单日期
    现在,我们可以轻松提供有关订单的完整信息,而无需致电产品服务。同样,这次订单服务对产品有太多的了解。有利的好处是,即使“产品”服务关闭,“订单”服务也可以提供相关数据。

这些方法中的任何一种都可以视为最佳实践吗?还是有不同的解决方案?

1 个答案:

答案 0 :(得分:3)

在eShopOnContainers示例(https://github.com/dotnet-architecture/eShopOnContainers)中,他们在创建订单商品时添加以下字段:

        public void AddOrderItem(int productId, string productName, decimal unitPrice, decimal discount, string pictureUrl, int units = 1)

这将复制目录信息,但是,因为这是记录的时间点快照。这比链接到原始数据要安全得多。

在用户旅程的这一点上,您位于订单的域中,如果用户正在查看订单,则可以提供目录的链接。但是,订单服务应能够独立运行。链接回目录以获取有关产品的信息,可防止Order服务拥有其自身的数据。

一个噩梦般的场景是目录中的价格发生了变化……历史订单会发生什么?