ann*_*ijn 9 c# integration publish-subscribe event-sourcing microservices
情况如下。共有三种服务,一种服务是事件源,并使用事件总线(如 Azure 服务总线或 ActiveMQ)向其他两种服务(订阅者)发布集成或通知事件(发件箱模式)。
此设计的灵感来自.NET 微服务 - 架构电子书 - 订阅事件。
我想知道如果这些事件之一由于错误而无法传递,或者事件处理只是没有正确实现,会发生什么。
如果出现应用程序错误,我应该信任我的消息总线吗?
是的。
(编辑:阅读此答案后,请阅读@StuartLC 的答案以获取更多信息)
你描述的系统是一个最终一致的系统。它的工作假设是,如果每个组件都完成其工作,则所有组件最终都会收敛到一致的状态。
发件箱的工作是确保事件源微服务持久化的任何事件都持久可靠地传递到消息总线(通过事件发布者)。一旦发生这种情况,事件源和事件发布者就完成了——他们可以假设事件最终将被传递给所有订阅者。然后消息总线的工作就是确保这种情况发生。
消息总线及其订阅可以配置为“至少一次”或“最多一次”传递。(请注意,“恰好一次”交付通常是无法保证的,因此应用程序应该能够抵御重复或丢失的消息,具体取决于订阅类型)。
“至少一次”(Azure 服务总线称为“Peek Lock”)订阅将保留该消息,直到订阅者确认它已被处理。如果订阅者给出确认,消息总线的工作就完成了。如果订阅者以错误代码响应或没有及时响应,消息总线可能会重试传递。如果多次传递失败,消息可能会被发送到有害消息或死信队列。无论哪种方式,消息总线都会保留消息,直到它确认收到消息为止。
在重新发布事件时,是否应该将所有消息重新发布到所有主题,还是只能重新发布一个子集?
我不能代表所有消息传递系统,但我希望消息总线只重新发布到失败的订阅子集。无论如何,所有订阅者都应该准备好处理重复和无序的消息。
服务重新发布事件是否应该能够访问发布者和订阅者数据库以了解消息偏移量?
我不确定我是否理解“知道消息偏移量”的意思,但作为一般准则,微服务不应该共享数据库。共享数据库模式是一种契约。合同一旦建立,就很难更改,除非您完全控制其所有使用者(包括他们的代码和部署)。通常最好通过应用程序 API 共享数据以提供更大的灵活性。
或者订阅微服务是否应该能够读取发件箱?
消息总线的重点是将消息订阅者与消息发布者解耦。让订阅者明确知道发布者违背了这个目的,并且随着发布者和订阅者数量的增长可能难以维持。相反,依靠专用的监控服务和/或消息总线的监控功能来跟踪传递失败。
只是为了补充@xander 的出色回答,我相信您可能对您的事件总线使用了不合适的技术。您应该会发现Azure 事件中心或Apache Kafka更适合事件发布/订阅架构。与旧的服务总线方法相比,专用事件总线技术的优势包括:
考虑到这一点,:
如果出现应用程序错误,我应该信任我的消息总线吗?
是的,因为 xander 提供的原因。一旦发布者确认事件总线已接受该事件,发布者的工作就完成了,并且不应再次发送相同的事件。
挑剔,但由于您处于发布订阅架构(即 0..N 个订阅者)中,因此无论使用何种技术,您都应该将总线称为事件总线(而不是消息总线)。
这是死信队列的用例吗?
死信队列通常是点对点队列或服务总线交付体系结构的产物,即其中有一条命令消息(事务性地)用于单个或可能有限数量的接收者。在发布-订阅事件总线拓扑中,期望发布者监控所有订阅者的交付对发布者来说是不公平的。
相反,订户应承担弹性交付的责任。在 Azure 事件中心和 Apache Kafka 等技术中,每个消费者组的事件都是唯一编号的,因此订阅者可以通过监视消息偏移量来收到丢失消息的警报。
在重新发布事件时,是否应该将所有消息重新发布到所有主题,还是只能重新发布一个子集?
不,事件发布者永远不应该重新发布事件,因为这会破坏所有观察者订阅者的事件链。请记住,每个发布的事件可能有 N 个订阅者,其中一些订阅者可能在您的组织之外/在您的控制之外。事件应被视为在某个时间点发生的“事实”。事件发布者不应该关心事件的订阅者是 0 还是 100。由每个订阅者决定如何解释事件消息。
例如,不同类型的订阅者可以对事件执行以下任何操作:
因此,您可以看到,为了一个 flakey 订阅者的利益而重新发布事件会破坏其他订阅者的数据流。
服务重新发布事件是否应该能够访问发布者和订阅者数据库以了解消息偏移量?
正如 xander 所说,系统和微服务不应该共享数据库。但是,系统可以公开 API(RESTful、gRPC 等)
事件总线本身应该跟踪哪个订阅者读取了哪个偏移量(即每个消费者组、每个主题和每个分区)。每个订户将能够监视和更改其偏移量,例如在事件丢失并需要重新处理的情况下。(同样,一旦确认事件已被总线接收,生产者就不应该重新发布事件)
或者订阅微服务是否应该能够读取发件箱?
事件驱动的企业架构至少有两种常见的方法:
Customer Y has purchased Product Z。在这种情况下,许多订阅者会发现事件中包含的信息不足以完成下游工作流,并且需要丰富事件数据,通常是通过调用靠近发布者的 API,以便检索其余数据他们需要。这种方法具有安全优势(因为 API 可以验证对更多数据的请求),但会导致 API 上的高 I/O 负载。| 归档时间: |
|
| 查看次数: |
644 次 |
| 最近记录: |