在传统的微服务架构中,您在某些消息传递系统上发布了相关的域事件,允许系统的其他部分做出反应。
现在假设您有三个微服务:客户,订单和推荐。 Recommendation 微服务需要来自 Customers 和 Orders 的信息来提供其功能,例如所有客户的列表和所有订单从一些机器学习算法分析。 现在,您需要让客户在“推荐”微服务上“加入”订单状态:
您有推荐的微服务监听客户和订单发布的域事件并构建自己的状态。这导致逻辑重复,因为您可能已经在客户和订单中具有相同的逻辑
在客户和订单的每个相关域消息中,您只需转到它们并询问特定客户或订单的状态。这样可以正常工作,但是如果您有N个服务而不是只需要构建物化视图的服务,那么您将对客户和订单造成很大负担
您获得客户和订单自己发布“重量级”事件(不是域事件),允许任何其他微服务构建物化视图而不处理域事件。这允许你们a)不要复制逻辑b)不要继续询问相同的信息
模式n.3有一些我们无法弄清楚的缺点,如果没有,你如何在Lagom中实现它?
答案 0 :(得分:3)
我将尝试解释一些内容,希望能为您提供更多关于此事的观点,以及如何在Lagom中以可靠的方式实现它。
我们必须牢记一些概念。最重要的一个是事件采购本身。事件采购意味着系统中的任何状态都有事件来源。
我们将要处理的第一个国家是持久性国家。此状态非常突出,因为它与命令和事件处理程序一起定义了模型的一致性边界。
但该系统中还有其他国家。实际上,我们可以创建尽可能多的东西,因为我们有Event Journal。读模型也是一个状态,它也是从事件中生成的。
有很多原因导致您不应将PersistentEntity的状态发布到其他系统。第一个是避免耦合的问题。您不希望您的数据泄露给其他服务。这就是拥有反腐败层(ACL)。
因此,从这里我们可以说:在将Order和Customer发布到推荐服务之前,我会将其转换为OrderView和CustomerView(ACL 101)。
现在的问题是你什么时候做?如果您在处理命令后尝试在Kafka中发布它,则无法保证将发布State。事件日志和Kafka主题之间没有XA事务。因此,事件有可能持续存在,但出于某种原因,国家不会在卡夫卡出版。
如果您希望数据以可靠的方式退出服务而不在服务之间创建耦合,则可以使用以下选项:
使用代理API并将事件发布到主题。您不应该按原样发布事件,而是将它们转换为外部API(ACL)的格式。 使用读取端处理器生成它的视图,再次使用您想要提供的外部API格式。如果需要,可以将ViewState发布到主题,以便其他服务可以直接使用它。
也就是说,在一个不是真实事件的主题中发布某些东西,但是某些派生状态是没有错的。问题是如何保证它的有效发布。从PersistentEntity内部执行此操作是有风险的,因为您具有最多一次的语义。最可靠的方法是一个读取端进程,它为您提供至少一次的语义。
进一步评论内联......
收听来自客户和订单的域事件并重建状态 在推荐服务中。这是一个可怕的想法,因为你 需要复制处理不同事件的逻辑 有界背景
这不是一个可怕的想法。这就是你如何让你的服务彼此独立。您需要实现以消耗事件的逻辑是不一样的。正如你所说,它是一个不同的有界背景,因此它只能得到它所需要的东西。
由于我上面提到的原因(反腐败层),将国家从卑诗省泄露到另一个国家更成问题。
要实现解耦,您需要更多编码,并且没有任何问题。在一天结束时,构建微服务的原因是避免耦合,并且能够让服务进化和扩展而不会相互干扰。这需要付出代价,而且价格是编写更多代码。你需要评估线程。
您可以使用自己的活动,制作 OrderView 和 CustomerView 并发布到Kafka,但这与直接在推荐上使用活动相同服务。
请注意,您还需要在推荐服务中的某处存储 OrderView 和 CustomerView 。所以你最终存放了三次。在原始服务(视图表)上,在Kafka和推荐服务中。
这就是为什么在主题中发布事件是在服务之间传播数据的最佳选择。
每次我们收到客户或订单的域名活动时,请转到 他们并问他们国家。这太可怕了,因为如果你有更多 比一个需要他们的状态的微服务,你最终会 对客户和订单产生负担
这确实是一个可怕的想法,因为您将使推荐服务依赖于其他两项服务。如果订单或客户关闭,建议书也将关闭。这是经纪人帮助解决的问题。
客户和订单不仅要发布事件,还要发布状态和 拥有构建物化视图所需的所有服务 他们需要的状态你如何应用Lagom的最后一个模式?我们 发现没有办法听取状态变化,只是为了事件。一个解决方案 我们考虑隐含在pubEub中发布onEvent中的状态 持久化实体的处理程序,但我不确定这是否正确 实现它的地方。
在onEvent处理程序中使用pubSub是最糟糕的解决方案。原因如下:
pubSub最多只有sematincs(见上面的评论)
多次调用事件处理程序。每当您重新补充实体时,都会重放事件并使用事件处理程序。这意味着您每次都会重新发布状态。实际上,你会解决最多一次的pubSub问题,但不是你想象/希望的方式。
您可以使用afterPersist回调,但由于pubSub最多只能使用一次,因此不可靠。
PersistentEntity中的PubSub不应该用于您需要可靠的东西。它是一种尽力而为的能力,这就是全部。