我对微服务架构中的事件源有疑问。
假设每个服务都将其事件存储在自己的事件存储中,如果投影需要来自多个服务的数据,我该如何重建读取模型?
例如,我们有UserService和InvoiceService。 在发票服务模型中,我仅使用用户ID,但在读取模型中,我还需要用户名,以便于查询。
谢谢,我现在有以下选择:
我错过了什么吗?有人知道更简单的解决方案吗?
答案 0 :(得分:1)
我同意选项1是不明智的。域模型(CQRS中的更新模型,而不是读取模型)应仅具有指向其他域的主键指针,而不支持来自那些域的数据。
选项2更好,但仍然不尽人意。我不喜欢使用事件采购时域之间的API调用,因为这可能会导致一个域失败或由于第二个域的困难而显得缓慢。在您的示例中,让Invoice域调用User域上的API来获取读取模型重建的用户名,这意味着如果User域关闭,Invoice域将无法完成其重建– Invoice域本身不会发生故障。
请考虑在发票域中缓存用户信息的选项3。在Invoice域中为适当的User事件创建侦听器,并在其中缓存必要的用户数据-在这种情况下,仅是主键和用户名,但是以后可以根据需要添加更多字段。然后,使用此缓存重新构建您的发票读取模型,因此不依赖于User域。
对于那些刚接触CQRS的读者来说,只需做个说明便可以确保我们都在同一页上。发票读取模型应在其中包含用户标识和用户名,而域模型应仅包含用户标识。读取模型到处都有重复的信息,并且不打算用作第三范式;它们的速度非常快,并且包含将在屏幕上显示的所有信息。
答案 1 :(得分:0)
用户可以拥有多个发票,并且从事件源使用唯一的用户名重播/重建模型并不理想(或者至少从我的理解来看)。我更喜欢的路线是拥有a co-relation identifier
。顾名思义,它将帮助您在作为给定业务任务/动作的一部分而发生的服务调用/事件源记录之间建立相互关系。在重新构建模型(无论是在仪表板中显示还是在执行模型/动作重播的逻辑)方面,有一些相互关联的内容很重要。通过快速搜索,我发现了a talk about的关联ID。请继续阅读并详细了解它,看看这种方法是否可以解决您的业务问题。
答案 2 :(得分:0)
假设每个服务都将自己的事件存储在自己的事件存储区中, 如果投影需要更多数据,我该如何重建读取模型 比一项服务?
我认为您错过了事件存储的概念。服务不应具有自己的事件存储。假设您正在通过服务发布事件,而其他一些服务将必须订阅事件流。您的事件存储区是所有服务的唯一真实来源。
以这种方式,如果您需要从多个流创建投影,则可以执行此操作。请查看this blog post。
现在,如果您不想在事件存储端构建投影,该怎么办。假设您有一个新要求,要显示包含发票计数,总账单等的用户报告。然后,我将执行以下操作-
订阅以侦听UserService(新订阅)中的UserCreated,UserBasicInfoUpdated事件
订阅以侦听InvoiceService(新订阅)中的InvoiceGenerated事件
构建新的读取模型
然后将先前的订阅(如果有)合并到新的订阅中。这个很重要。因为您不应有多个订阅者同时参与同一事件。