CQRS / ES架构中的有界上下文之间的通信是通过事件实现的; context A生成事件作为对命令的响应,然后通过事件总线(消息队列)将这些事件转发到上下文B.
或者......您可以将事件存储在eventstore中(属于上下文A)。 或者......两者(存储和前进)。
我的问题是:从上下文B,我应该从上下文存储中提取事件吗?或者只是通过事件总线消耗推送事件?
我倾向于拉动方式。因为那时我们可以在上下文B中进行一些追赶。相反,在推送方法中,上下文B可能不知道在B遇到停机时传递的事件。
所以......这意味着......当我们有eventstore时,我们可以简单地忘记消息队列(似乎是多余的)?
或者我在这里遗漏了什么?
答案 0 :(得分:6)
您想要查看Consume event stream without Pub/Sub
在DDD欧洲会议上,我意识到与我交谈的发言人(sic)尽可能避免发布/发布。
以下讨论可能有价值。 TL; DR:没有很多酒吧/派对的粉丝。
<{3}}上的Konrad Garus,描述了Pull设计:在后一种(和更简单的)设计中,它们只传播已保存新事件的信息及其顺序ID(以便所有预测可以估计它们背后有多少)。唤醒后,执行程序可以继续其正常路径,从查询事件存储开始。
为什么呢?因为来自单个源的处理事件更容易,但更重要的是因为DB支持的事件存储可以简单地保证排序,并且不会丢失或重复消息。鉴于我们按主键顺序读取单个表,并且大多数时候数据仍在RAM缓存中,因此查询数据库的速度非常快。瓶颈在于投影线程更新其读取模型数据库。
在大型方面,它归结为:当人们考虑事件采购时,他们真的在考虑历史,而不是孤立的事件。如果你真正想要的是一个没有间隙的有序事件序列,那么查询该序列的权限比尝试从一堆不相交的事件消息中重建更好。
但是 - 一旦你决定这样做,那么突然之间历史以及其中出现的所有事件都会成为上下文api的一部分。当团队A决定不同的事件存储实现更多时会发生什么适当?他们可以推出自己服务的新版本,还是需要大量停机,因为每个消费者都必须更新?
同样,如果我们决定将上下文A重构为上下文C和上下文D,会发生什么?同样,我们是否必须在上下文B中搞砸以获取我们需要的数据?
也许真正的问题是上下文B与上下文A中的历史相关联,那些历史应该是私有的吗?上下文B应该访问上下文A的数据,还是应该将该工作委托给上下文A的功能?
Udi Dahan Push or Pull?可能会朝着这个方向开始思考。