CQRS / 上下文之间的通信 / 事件存储 / 推还是拉?

CQRS / communication between contexts / eventstore / push or pull?

CQRS/ES架构中限界上下文之间的通信是通过事件实现的;上下文 A 生成事件作为对命令的响应,然后这些事件通过事件总线(消息队列)转发到上下文 B。

或者...您可以将事件存储在 eventstore(属于上下文 A)中。 或者...两者(向前存储 )。

我的问题是:从上下文 B,我应该从上下文存储中提取事件吗?或者简单地通过事件总线消费 pushed 事件?

我倾向于拉式方法。因为这样我们就可以在上下文 B 中进行一些追赶。相比之下,在推送方法中,上下文 B 可能不知道在 B 遇到停机时交付的事件。

所以...这是否意味着...当我们有了 eventstore 时,我们就可以简单地忘记消息队列(似乎是多余的)?

还是我漏掉了什么?

您需要查看 Consume event stream without Pub/Sub

At the DDD Europe conference, I realized that the speakers I talked with where (sic) avoiding Pub/Sub whenever possible.

下面的讨论可能有价值。 TL;DR:pub/sub 的粉丝不多。

Konrad Garus 在 Push or Pull? 上描述了 Pull 设计:

In the latter (and simpler) design, they only spread the information that a new event has been saved, along with its sequential ID (so that all projections can estimate how much behind they are). When awakened, the executor can continue along its normal path, starting with querying the event store.

Why? Because handling events coming from a single source is easier, but more importantly because a DB-backed event store trivially guarantees ordering and has no issues with lost or duplicate messages. Querying the database is very fast, given that we’re reading a single table sequentially by primary key, and most of the time the data is in RAM cache anyway. The bottleneck is in the projection thread updating its read model database.

总的来说,归结为:当人们考虑事件溯源时,他们实际上是在考虑历史,而不是孤立地考虑事件。如果您真正想要的是一个没有间隙的有序事件序列,那么查询该序列的权限比尝试从一堆不相交的事件消息中重建要好得多。

但是 - 一旦您决定这样做,突然之间,历史记录以及其中出现的所有事件都会成为上下文 A api 的一部分。当团队 A 决定不同的事件存储实现更合适?他们可以推出他们自己服务的新版本,还是我们需要大停电,因为每个消费者也必须得到更新?

同样,如果我们决定将上下文 A 重构为上下文 C 和上下文 D,会发生什么情况?同样,我们是否必须在上下文 B 中搞砸才能获得我们需要的数据?

也许真正的问题是上下文 B 与上下文 A 中的历史耦合,而那些历史真的应该是私有的?上下文 B 应该访问上下文 A 的数据,还是应该将该工作委托给上下文 A 的功能?

Udi Dahan essays on SOA 可能会让你开始朝那个方向思考。