适当分离微服务之间的关注点
Proper separation of concerns between microservices
假设我想创建一个允许管理用户帐户的博客平台,因此我提出了 2 个微服务:
Blogging
- 管理帖子、标签等
Users
- 管理用户、他们的角色等
我很清楚 Post
包含作者 (User
) 的 ID,User
包含他写的 Posts
的 ID。
问题是,当客户端请求一个Post
时,我还想return作者的名字,并在一个DTO(视图模型)中一起发送给客户端。我看到了 2 种可能的解决方案:
- 在
Blogging
服务的域中引入User
(仅ID和名称)的概念。每次客户端请求 Post
时,所有相关数据都仅从此微服务中获取。每次在 Users
微服务中修改用户名时,都会通知此服务并更新作者姓名。
- 将关注点完全分开。每次客户端请求
Post
,调用Blogging
微服务获取Post
,然后调用Users
微服务根据ID获取作者姓名。
到目前为止,我倾向于解决方案 #1,因为当请求 Post
时,它只需要对 1 个微服务调用 1 次,但是如果函数(微服务)的数量开始增长并且我继续从它们每个人中添加小概念只是为了限制调用次数,恐怕我最终会变成意大利面 Blogging
微服务......但我也不认为微服务的数量会增长显着 ;)
你觉得哪种方式更好,为什么?是否有任何方法违反了微服务架构原则,我的担忧是否合理?
这实际上取决于您的程序的开发方式。
解决方案 #1(编辑 Blogging
模型)
为了性能,您在这里编辑模型。大多数时候我不认为为了性能而改变模型本身是正确的方法。如果您认为 Blogging
上下文中的 User
的概念不正确,则不应将其放在那里。另一个问题是您必须在有界上下文 (BC) 之间处理 eventual consistency。如果您认为 Blogging
中的 User
的概念不是一个坏主意,那么它可能是可行的方法。
解决方案#2(单独查询数据)
虽然这可能性能不友好,但我认为这在开始时是最简单的方法。您不必处理最终一致性(+处理 BC 之间的数据同步),也不必更改模型。但是,如果您真的关心性能并保持模型清洁,您可能会对 read model.
感兴趣
另一种解决方案——读取模型
读取模型的概念是至少有两个独立的模型:一个用于读取数据,另一个用于writing/editing 数据。如果我们想为您的问题实施这个概念,我们将为 Blogging
BC 创建一个读取模型,其中 Posts
和 Users
可以合并在一起(类似于解决方案 #1)和然后查询。我们可以借助事件来同步这些数据,因此当 Post
或 User
更改时,它会引发一个事件并将更改的数据保存到您的读取模型中。这样你就可以 merge/alter 任何你想要的数据以获得更好的性能。它可能与解决方案 #1 非常相似,但主要区别在于您不编辑主模型。您创建新的只是为了阅读。这可能是最难的解决方案,但如果您的项目很大且性能要求很高,这可能是一种方法。
我不会说任何解决方案对于解决您的问题来说是最好的或最坏的。它总是取决于上下文。
假设我想创建一个允许管理用户帐户的博客平台,因此我提出了 2 个微服务:
Blogging
- 管理帖子、标签等Users
- 管理用户、他们的角色等
我很清楚 Post
包含作者 (User
) 的 ID,User
包含他写的 Posts
的 ID。
问题是,当客户端请求一个Post
时,我还想return作者的名字,并在一个DTO(视图模型)中一起发送给客户端。我看到了 2 种可能的解决方案:
- 在
Blogging
服务的域中引入User
(仅ID和名称)的概念。每次客户端请求Post
时,所有相关数据都仅从此微服务中获取。每次在Users
微服务中修改用户名时,都会通知此服务并更新作者姓名。 - 将关注点完全分开。每次客户端请求
Post
,调用Blogging
微服务获取Post
,然后调用Users
微服务根据ID获取作者姓名。
到目前为止,我倾向于解决方案 #1,因为当请求 Post
时,它只需要对 1 个微服务调用 1 次,但是如果函数(微服务)的数量开始增长并且我继续从它们每个人中添加小概念只是为了限制调用次数,恐怕我最终会变成意大利面 Blogging
微服务......但我也不认为微服务的数量会增长显着 ;)
你觉得哪种方式更好,为什么?是否有任何方法违反了微服务架构原则,我的担忧是否合理?
这实际上取决于您的程序的开发方式。
解决方案 #1(编辑 Blogging
模型)
为了性能,您在这里编辑模型。大多数时候我不认为为了性能而改变模型本身是正确的方法。如果您认为 Blogging
上下文中的 User
的概念不正确,则不应将其放在那里。另一个问题是您必须在有界上下文 (BC) 之间处理 eventual consistency。如果您认为 Blogging
中的 User
的概念不是一个坏主意,那么它可能是可行的方法。
解决方案#2(单独查询数据)
虽然这可能性能不友好,但我认为这在开始时是最简单的方法。您不必处理最终一致性(+处理 BC 之间的数据同步),也不必更改模型。但是,如果您真的关心性能并保持模型清洁,您可能会对 read model.
感兴趣另一种解决方案——读取模型
读取模型的概念是至少有两个独立的模型:一个用于读取数据,另一个用于writing/editing 数据。如果我们想为您的问题实施这个概念,我们将为 Blogging
BC 创建一个读取模型,其中 Posts
和 Users
可以合并在一起(类似于解决方案 #1)和然后查询。我们可以借助事件来同步这些数据,因此当 Post
或 User
更改时,它会引发一个事件并将更改的数据保存到您的读取模型中。这样你就可以 merge/alter 任何你想要的数据以获得更好的性能。它可能与解决方案 #1 非常相似,但主要区别在于您不编辑主模型。您创建新的只是为了阅读。这可能是最难的解决方案,但如果您的项目很大且性能要求很高,这可能是一种方法。
我不会说任何解决方案对于解决您的问题来说是最好的或最坏的。它总是取决于上下文。