【发布时间】:2017-04-29 03:13:34
【问题描述】:
我正在使用 Java 和 Cassandra 的事件源从头开始构建一个项目。 我的应用程序基于微服务,在某些用例中信息将被异步处理。我想知道消息队列(例如 Rabbit、Active MQ Artemis、Kafka 等)将发挥什么作用来改进这种环境中的技术堆栈,以及如果我不使用它是否了解这些场景。
【问题讨论】:
标签: asynchronous message-queue event-sourcing
我正在使用 Java 和 Cassandra 的事件源从头开始构建一个项目。 我的应用程序基于微服务,在某些用例中信息将被异步处理。我想知道消息队列(例如 Rabbit、Active MQ Artemis、Kafka 等)将发挥什么作用来改进这种环境中的技术堆栈,以及如果我不使用它是否了解这些场景。
【问题讨论】:
标签: asynchronous message-queue event-sourcing
确保您清楚发送(命令)和发布(事件)之间的区别。 Udi Dahan 在他的 busses and brokers 文章中谈到了这个话题。
在您进行事件溯源的大多数情况下,您确实不希望从已发布的事件中重建状态。如果您需要状态,则查询历史的技术权威/记录簿,并从历史中重建状态。
另一方面,消息队列中的事件驱动 活动应该没问题。当单个事件(加上订阅者的状态)拥有您需要的一切时,就可以离开总线了。
在某些情况下,您可能会同时使用这两种方法。例如,如果您正在更新缓存视图,您将订阅各种BobChanged 事件以了解您的缓存数据何时过时;要重建陈旧的视图,您需要重新加载历史的表示并将其转换为更新的视图。
【讨论】:
在事件源应用程序的世界中,消息队列通常允许您在生产者和消费者之间实现发布-订阅模式的通信方式。此外,它们通常会帮助您提供传递保证:哪些消息已传递给哪些订阅者,哪些未传递。
但它们不会无限期地存储所有消息。您需要有一个事件存储来执行任何类型的事件采购。
问题不是“排队还是不排队”,而更像是:
因此,您应该使用Kafka 或EventStore 之类的东西来开箱即用。或者,您可以手动将事件存储与消息队列结合起来,但这会涉及更多。
【讨论】:
我会先将 RabbitMQ 等消息传递基础设施与 Kafka 等事件流/存储/处理分开。这是为两个(或更多)不同目的而制造的两种不同的东西。
关于事件溯源,您必须有一个必须存储事件的地方。此存储必须是仅附加的,并且支持基于身份的非结构化数据的快速读取。这种持久性的一个例子是EventStore。
事件溯源与 CQRS 一起使用,这意味着您必须将您的更改(事件)投射到您可以查询的另一个商店。这是通过将事件投影到该存储来完成的,这是处理事件以更改域对象状态的地方。重要的是要了解使用消息基础设施进行预测通常是一个坏主意。这是由于消息传递的性质和两阶段提交问题。
如果您查看事件是如何持久化的,您会发现它们作为一个事务保存到存储中。如果您随后需要发布事件,这将是另一个事务。由于您要处理两个不同的基础架构,因此可能会出现问题。
这样的消息传递问题是消息通常保证“至少一次”传递,并且消息的顺序通常不能保证。此外,当您的消息使用者失败并 NACK 消息时,它会重新传递,但通常会稍晚一点,再次破坏序列。
无论是谁,排序和重复问题都不适用于 Kafka 等事件流服务器。此外,如果您使用追赶订阅,EventStore 将保证仅按顺序发送一次事件。
根据我的经验,消息用于发送命令和实现事件驱动架构,以反应方式连接独立服务。另一方面,事件存储用于持久化事件,只有到达那里的事件才会投射到查询存储并发布到消息总线。
【讨论】: