我们有一个非常普遍的情况:每个聚合,命令,事件等都包含某种审核日志:是谁创建的?谁做了最后修改?什么时候?
基本上,每个读取模型也需要包含此数据,因为客户端需要显示此信息。
为简单起见,请想象一下StackOverflow的问题的阅读模型(包括所有相应的答案和评论)。
读取模型包含许多用户:谁创建了问题?谁做了最后修改?而且,每个评论和答案以及答案的评论都使用相同的数据。
现在考虑一个更大的平台,其中包含更多的读取模型,基本上每个读取模型都需要相同的用户信息。
我现在遇到了4种不同的解决方案,但是我不确定要选择哪种解决方案。或者也许还有更好的东西?
仅将userId
存储在读取模型中。客户端必须查询User Service
才能获得用户名。
自包含微服务(使用事件):每个服务都存储User数据库的迷你副本(仅id,name)。
耦合的微服务:对于来自客户端的每个请求,每个服务都会在User Service
中查询用户名。
将整个用户数据库加载到客户端的缓存中,然后使用它。
缺点是:
如果User Service
无法访问,则客户端无法显示所有必要的信息。另外,客户端必须从响应中提取所有userId
,并向User Service
发出单独的请求。
聆听UserCreatedEvent
以便将整个User数据库复制到每个微服务是很多重复的代码和数据。
与方法1相同的问题:如果User Service
无法访问,则无法显示信息。当然,这会引入高耦合,大量网络流量等。
对于我们当前的项目来说这是不可能的,因为用户太多了,可以经常添加新用户。
到目前为止,方法2 对我来说似乎是最好的,因为它应该是最有弹性的。而且可以将代码重复提取到某个common module
中,该记录可以跟踪UserCreatedEvent
并提供一些api /回调机制。
您如何在项目中解决此问题?您还有其他优点/缺点吗?
答案 0 :(得分:0)
除了您提到的利弊外,我还会在做出决定之前添加一些要问自己的观点或问题:
- 如果无法访问用户服务,则客户端无法显示所有必要的信息。另外,客户必须提取所有 响应中的userIds并向User发出单独的请求 服务。
在一段时间内某些屏幕上的用户信息不可用真的很不好吗?如果用户服务关闭,则最小的问题之一就是某些屏幕没有完整的用户信息。 :)同样,对于客户端来说,提取所有ID并进行单独调用不是那么麻烦吗?可能有问题的是您要从中获取用户ID的数量 用户服务。这完全取决于您要显示的记录数量和用例。
- 监听UserCreatedEvents以便将整个User数据库复制到每个微服务是很多重复的代码, 数据。
在这种情况下,它不会将整个User数据库复制到每个服务。从您给出的有关堆栈溢出问题/示例的示例来看,它将是一小部分数据子集,例如:id和userName。某种问题列表将包含所有问题,其中userId是询问该问题的用户名。然后,如果有人想查看有关该用户的更多信息,则只有在这种情况下,他才会致电用户服务。另一方面,不是每个用户都问一个问题和/或回答问题。仍然是一个有效的观点,如果您在所有服务中都这样做,则会有很多重复。我想说您不必在所有服务中都使用这种方法。仅使用适合的数据和可能较少的用户数据的数据。
- 与方法1相同的问题:如果无法访问用户服务,则无法显示信息。当然这 会引入高耦合,大量网络流量等。
此选项与1.选项相比,要多加一点。与从一个微服务到另一个微服务的本地调用相比,从外部客户端(WebApp,移动应用)到某些Rest API的调用这一事实可能要慢得多。通常,即使微服务不在同一服务器上,它们也可能在同一群集中,所以从一个到另一个的调用将在同一网络内,因此比来自某些客户端应用程序的调用要快。在大多数情况下,这不是很多,但是如果您有很多电话,那么您也可以考虑使用它。
一般建议
您应该检查每个微服务如何与用户数据一起使用,并基于此决定重复或调用用户微服务。我会视情况决定。两种方法(选项1或选项2)各有利弊。