首页 > 解决方案 > 如何跨多个微服务(或模块化单体中的模块)实现读取端?

问题描述

在我们可能需要一些需要跨不同限界上下文的数据读取的场景中(换句话说,无论是来自多个微服务还是模块化单体的模块),实现它的方法是什么?

我能想到的一对是:

  1. 什么都不做,让客户端通过调用多个服务来编译它需要的视图并合并它需要的数据
  2. 创建单独的模块,从每个微服务/模块获取数据,编译读取模型并将其公开给客户端
  3. 有单独的模块和物化视图,每次涉及的数据发生变化时都会更新(通过不同的微服务)。

有一些“最佳实践”的方法吗?如果是这样,为什么?

标签: microservicesdomain-driven-design

解决方案


我很快就会面临类似的情况。我对此的看法:

1和2本质上是相同的方法。具体来说,“客户端”无论是最终客户端 (1) 还是组成多个调用的单独模块 (2),都将调用多个模块以在根据需要编译成单个视图之前从每个模块获取相关数据。

我看到了三种潜在的架构:

  1. 您没有全局数据库,每个模块都使用相同的数据模型进行写入和读取。
  2. 您没有全局数据库,每个模块都有一个用于写入和读取的单独数据库(当命令更改写入模型时,使用内部事件来同步读取模型)。
  3. 您有一个全局数据库来处理来自各个模块的集成事件以编译全局读取数据库。

对于我的解决方案,我希望达到第 3 位。然后可以实现一个单独的全局查询模块以从全局数据库返回结果,而无需处理这些模块。这将保持模块写入数据库自由以最佳响应命令,而不会同时对数据库进行潜在的复杂读取。

第 2 项将使模块写入数据库保持最佳状态,但需要对不同的模块读取数据库进行多次查询才能为客户端编译单个视图。

数字 1 是最不利的,因为它会访问每个模块中用于写入的同一数据库,并且还需要一个层来将来自不同模块的多个查询编译到全局视图中。

我的攻击计划将分阶段进行:

首先,创建一个“整理层”,公开查询以返回客户端的全局视图。我会回避让最终客户端进行组合,因为您的模块架构中的任何更改都会直接影响客户端而不是您的“整理层”。整理层可以保护最终客户端免受此类更改的影响。

最初,我有架构 1。因此,我的整理层确实会访问与模块用于写入的数据库相同的数据库。但它很快就开始了。

但是,在建立了该排序层之后,我可以在不影响客户端接口的情况下优化我的底层解决方案。到那时,我应该对全局数据模式的外观有一个清晰的认识,所以我会直接将我的架构更改为数字 3。在开发过程中尝试架构 3 的问题是,我可以想象维护模块中的更改以及全局数据模型中相应的潜在更改会使事情变得太慢。

架构 2 在开发过程中更容易实现,因为读取模型只会受到本地模块更改的影响。

根据您在开发和初始发布期间对模块的相同数据库进行读写的敏感度,架构 2 可能是您的一个不错的垫脚石。

对我来说,我很高兴在初始版本(少量客户)中使用相同的模块数据库进行隐藏在整理层接口后面的读取和写入,因此我可以在更多客户加入之前直接跳到架构 3 .

正如我在 DDD 中发现的那样,正确的方法通常取决于......

不是这样的答案,但也许这些想法会帮助你做出自己的决定。


推荐阅读