分解成微服务
Decomposition into microservices
我有一个关于分解成微服务的问题。假设我们有 2 个微服务:User 和 Product。假设我们现在有一个向系统添加类别的需求。更具体地说,一个产品有一个或多个类别(例如产品红色微型法拉利属于玩具和汽车类别),用户可以有她喜欢的类别(例如玩具和鞋子)。现在,当我们检索完整的产品列表时,我们希望对它们进行排序,以便属于首选用户类别的产品位于顶部。
基本上是微服务之间共享的概念(在本例中为类别)。如何在微架构环境中对此进行最佳建模?我看到两个解决方案:
解决方案一:
- 创建一个单独的“类别”微服务来管理类别的 CRUD
- 在产品服务中 API 调用产品的 link 类别 ID
- 在用户服务中 API 调用 link 类别 ID 给用户
- 在产品服务中,我们有一个 API 调用来获取按偏好订购的产品。为了完成这项工作,产品服务需要调用用户服务来获取用户类别(或监听用户服务发出的事件)
方案二:
创建一个单独的“类别”微服务来管理类别的 CRUD
类别服务还有一个 API 调用 link 产品 ID 到类别
类别服务还有一个 API 调用 link 用户 ID 到类别
在产品服务中,我们有一个 API 调用来获取按偏好订购的产品(要使此工作产品服务需要调用类别服务来获取用户和产品类别(或监听事件)
两种解决方案的 advantages/disadvantage 是什么?
我会说你应该有一个更复杂的服务,三个简单的服务。你的分类服务应该只是分类的CRUD,你的用户服务应该是用户的CRUD,你的产品应该更复杂,称之为产品列表服务,然后仍然有一个简单的产品服务。
您的产品列表服务应该具有所有的复杂性,但可能是非规范化的。
GET/POST/PUT/DELETE /product
GET/POST/PUT/DELETE /category
GET/POST/PUT/DELETE /user
POST/PUT /productlisting/usercategory/<userid> <list of categories>
POST/PUT /productlisting/productcategory/<productid> <list of categories>
GET /productlisting
要么这样,要么将它们全部组合成一个整体......它们不是单独的问题,通过 ID 耦合它们只会让你在长期运行中感到难过,因为你的耦合将是脆。我从不让一项服务知道另一项服务的实体 ID。分布式系统中的这种关系约束只是自找麻烦。
好吧,解决方案 2 已出局,因为您将对不同服务中的许多事物使用类别,这会破坏关注点分离,使类别服务在所有这些不同域中实现搜索。
此外,除了类别之外,现实的产品或用户搜索还可以包括其他标准。让针对所有这些不同条件的服务实现自己的产品搜索通常不是一个好的实现,因为在多条件搜索中合并结果可能代价高昂,因此这种在定义条件对象的服务中实现搜索的模式确实不按比例。
方案一接近,但没有理由让产品服务知道或调用用户服务。产品服务应该有一个 API 来使用各种标准搜索产品,包括类别。通过让客户端传递类别 ID 列表而不是用户 ID 来实现类别搜索可能会更好。这样它就不必自己调用用户服务,并且您可以使产品和用户服务保持独立。此外,按类别搜索产品对于其他事情(例如浏览产品!)也很有用,并且由于您没有将类别搜索与用户联系起来,您可以使用相同的 API 来处理其他情况。
替代的第三种解决方案是不要让微服务只是表。将 "things" 与 CRUD 功能放在单独的服务中的问题在于,大多数时候,它们会有很多交叉依赖关系。这就是你现在遇到的问题。
您可以制作与功能而非数据相符的服务。制作 "search" 服务、"shopping cart" 服务、"billing" 服务等。所有这些通常需要相同 "thing"(例如产品)的不同方面。我可以想象这些类别仅与 "search" 相关,但与其他两个无关。
有些人已经写过这种方法 here, named Self-Contained Systems。
我有一个关于分解成微服务的问题。假设我们有 2 个微服务:User 和 Product。假设我们现在有一个向系统添加类别的需求。更具体地说,一个产品有一个或多个类别(例如产品红色微型法拉利属于玩具和汽车类别),用户可以有她喜欢的类别(例如玩具和鞋子)。现在,当我们检索完整的产品列表时,我们希望对它们进行排序,以便属于首选用户类别的产品位于顶部。
基本上是微服务之间共享的概念(在本例中为类别)。如何在微架构环境中对此进行最佳建模?我看到两个解决方案:
解决方案一:
- 创建一个单独的“类别”微服务来管理类别的 CRUD
- 在产品服务中 API 调用产品的 link 类别 ID
- 在用户服务中 API 调用 link 类别 ID 给用户
- 在产品服务中,我们有一个 API 调用来获取按偏好订购的产品。为了完成这项工作,产品服务需要调用用户服务来获取用户类别(或监听用户服务发出的事件)
方案二:
创建一个单独的“类别”微服务来管理类别的 CRUD
类别服务还有一个 API 调用 link 产品 ID 到类别
类别服务还有一个 API 调用 link 用户 ID 到类别
在产品服务中,我们有一个 API 调用来获取按偏好订购的产品(要使此工作产品服务需要调用类别服务来获取用户和产品类别(或监听事件)
两种解决方案的 advantages/disadvantage 是什么?
我会说你应该有一个更复杂的服务,三个简单的服务。你的分类服务应该只是分类的CRUD,你的用户服务应该是用户的CRUD,你的产品应该更复杂,称之为产品列表服务,然后仍然有一个简单的产品服务。
您的产品列表服务应该具有所有的复杂性,但可能是非规范化的。
GET/POST/PUT/DELETE /product
GET/POST/PUT/DELETE /category
GET/POST/PUT/DELETE /user
POST/PUT /productlisting/usercategory/<userid> <list of categories>
POST/PUT /productlisting/productcategory/<productid> <list of categories>
GET /productlisting
要么这样,要么将它们全部组合成一个整体......它们不是单独的问题,通过 ID 耦合它们只会让你在长期运行中感到难过,因为你的耦合将是脆。我从不让一项服务知道另一项服务的实体 ID。分布式系统中的这种关系约束只是自找麻烦。
好吧,解决方案 2 已出局,因为您将对不同服务中的许多事物使用类别,这会破坏关注点分离,使类别服务在所有这些不同域中实现搜索。
此外,除了类别之外,现实的产品或用户搜索还可以包括其他标准。让针对所有这些不同条件的服务实现自己的产品搜索通常不是一个好的实现,因为在多条件搜索中合并结果可能代价高昂,因此这种在定义条件对象的服务中实现搜索的模式确实不按比例。
方案一接近,但没有理由让产品服务知道或调用用户服务。产品服务应该有一个 API 来使用各种标准搜索产品,包括类别。通过让客户端传递类别 ID 列表而不是用户 ID 来实现类别搜索可能会更好。这样它就不必自己调用用户服务,并且您可以使产品和用户服务保持独立。此外,按类别搜索产品对于其他事情(例如浏览产品!)也很有用,并且由于您没有将类别搜索与用户联系起来,您可以使用相同的 API 来处理其他情况。
替代的第三种解决方案是不要让微服务只是表。将 "things" 与 CRUD 功能放在单独的服务中的问题在于,大多数时候,它们会有很多交叉依赖关系。这就是你现在遇到的问题。
您可以制作与功能而非数据相符的服务。制作 "search" 服务、"shopping cart" 服务、"billing" 服务等。所有这些通常需要相同 "thing"(例如产品)的不同方面。我可以想象这些类别仅与 "search" 相关,但与其他两个无关。
有些人已经写过这种方法 here, named Self-Contained Systems。