使用Lagom的远程持久视图

在传统的微服务架构中,您在某些消息传递系统上发布了相关的域事件,允许系统的其他部分做出反应 .

现在假设您有三个微服务:客户,订单和推荐 . 推荐微服务需要来自客户和订单的信息来提供其功能,例如所有客户的列表和所有订单,这些将从一些机器学习算法进行分析 . Now, you need to have the state of Customers "join" Orders on the Recommandation microservice:

  • 您有推荐的微服务监听客户和订单发布的域事件并构建自己的状态 . 这会导致逻辑重复,因为您可能已经在Customers和Orders中拥有相同的逻辑

  • 在客户和订单的每个相关域消息上,您只需访问它们并询问特定客户或订单的状态 . 这样可以正常工作,但是如果您有N个服务而不是只需要构建物化视图的服务,那么您将对客户和订单造成很大的负担

  • 您获得客户和订单自己发布“重量级”事件(不是域事件),允许任何其他微服务构建物化视图而不处理域事件 . 这允许你们a)不复制逻辑b)不要继续询问相同的信息

有模式n.3我们无法弄清楚的一些缺点,如果没有,你如何在Lagom中实现它?

回答(1)

2 years ago

我将尝试解释更多的内容,希望能够为您提供更多关于此事的观点,以及如何在Lagom中以可靠的方式实现它 .

我们必须牢记一些概念 . 最重要的一个是所有人的来源 Event Sourcing 本身 . 事件采购意味着系统中的任何状态都有其事件来源 .

我们将要处理的第一个国家是持久性国家 . 此状态非常突出,因为它与命令和事件处理程序一起定义了模型的一致性边界 .

但该系统中还有其他国家 . 实际上,我们可以创建尽可能多的东西,因为我们有Event Journal . 读模型也是一个状态,它也是从事件中生成的 .

您不应将PersistentEntity状态发布到其他系统的原因有很多 . 第一个是避免耦合的问题 . 您不希望您的数据泄露给其他服务 . 这就是拥有反腐败层(ACL) .

因此,从这里我们可以说:在将Order和Customer发布到推荐服务之前,我将其转换为OrderView和CustomerView(ACL 101) .

现在的问题是你什么时候做?如果您在处理命令后尝试在Kafka中发布它,则无法保证将发布State . 事件日志和Kafka主题之间没有XA事务 . 因此,事件有可能持续存在,但出于某种原因,国家不会在 Kafka 出版 .

如果您希望数据以可靠的方式退出服务而不在服务之间创建耦合,则可以使用以下选项:

使用代理API并将事件发布到主题 . 您不应该按原样发布事件,而是将它们转换为外部API(ACL)的格式 . 使用读取端处理器生成它的视图,再次使用您想要提供的外部API格式 . 如果需要,可以将ViewState发布到主题,以便其他服务可以直接使用它 .

也就是说,在一个不是真实事件的主题中发布某些东西,但是某些派生状态是没有错的 . 问题是如何保证它的有效发布 . 从PersistentEntity内部执行此操作是有风险的,因为您具有最多一次的语义 . 最可靠的方法是一个读取端进程,它为您提供至少一次的语义 .

进一步评论内联......

从客户和订单中收听域事件,并在推荐服务中重建状态 . 这是一个可怕的想法,因为您需要复制处理跨不同有界上下文的事件的逻辑

这不是一个可怕的想法 . 这就是您使服务彼此独立的方式 . 您需要实现以消耗事件的逻辑是不一样的 . 正如你所说,它是一个不同的有界背景,因此它只能得到它所需要的 .

由于我上面提到的原因,将国家从卑诗省泄露到另一个国家更成问题(反腐败层) .

要实现解耦,您需要更多编码,并且没有任何问题 . 在一天结束时,构建微服务的原因是避免耦合,并且能够让服务进化和扩展而不会相互干扰 . 这需要付出代价,而且价格是编写更多代码 . 您需要评估线程 .

您可以使用自己的事件,生成 OrderViewCustomerView 并发布到Kafka,但这与直接在推荐服务上使用事件相同 .

请注意,您还需要在推荐服务中的某处存储 OrderViewCustomerView . 所以你最终存放了三次 . 在原始服务(视图表)上,在Kafka和推荐服务中 .

这就是为什么在主题中发布事件是在服务之间传播数据的最佳选择 .

每当我们收到客户或订单的域名活动时,请转到他们并询问他们的状态 . 这太可怕了,因为如果你有多个需要他们状态的微服务,你最终会对客户和订单产生负担

这确实是一个可怕的想法,因为您将使推荐服务依赖于其他两项服务 . 如果订单或客户关闭,建议书也将关闭 . 这就是经纪人帮助解决的问题 .

让客户和订单不仅发布事件而且还声明并拥有构建物化视图所需的所有服务,倾听他们需要的状态如何使用Lagom应用最后一个模式?我们发现没有办法听取状态变化,仅仅是为了事件 . 我们考虑的一个解决方案是暗示使用pubSub在持久化实体的onEvent处理程序中发布状态,但我不确定这是否是实现它的正确位置 .

在onEvent处理程序中使用pubSub是最糟糕的解决方案 . 原因如下:

  • pubSub最多只有一次sematincs(见上面的评论)

  • 事件处理程序被多次调用 . 每当您重新补充实体时,都会重放事件并使用事件处理程序 . 这意味着您每次都会重新发布状态 . 实际上,你会解决最多一次的pubSub问题,但不是你想象/期望的方式 .

您可以使用afterPersist回调,但这不可靠,因为pubSub最多只有一次 .

PersistentEntity中的PubSub不应该用于您需要可靠的东西 . 这是一种尽力而为的能力,就是这样 .