关于事件驱动拓扑中的中介者

Posted

技术标签:

【中文标题】关于事件驱动拓扑中的中介者【英文标题】:About the Mediator in Event-Driven Topology 【发布时间】:2018-03-26 07:40:05 【问题描述】:

我正在阅读这篇名为 Variations in event-driven architecture 的文章,他们在其中演示了中介和代理拓扑。

根据文章,中介拓扑看起来有点像这样:

事件流从客户端发送一个事件到一个事件队列开始,该队列用于将事件传输到中介。 事件中介接收初始事件并通过向事件通道发送额外的异步事件来编排该事件以执行流程的每个步骤。 事件处理器,它监听事件通道,从偶数中介接收事件并执行特定的业务逻辑来处理事件 [...] 需要注意的是,事件中介不实际执行处理初始事件所需的业务逻辑,相反,它知道处理事件所需的步骤 [...] 事件通道可以是消息队列或消息主题。

所以,我正在研究这个图表,试图了解中介如何确定给定处理器何时完成对给定事件的处理,以便它可以协调流程的下一步。

文章说的不够清楚

对于每个初始事件步骤,事件调解器创建一个处理事件,发送该处理事件并等待相应事件处理器处理该处理事件。这个过程一直持续到初始事件中的所有步骤都已处理完毕。

现在,文章清楚地表明通信是异步的,事件消息将通过消息队列传播,但该图没有显示任何从事件处理器出来并返回到中介者的事件.

文章说调解器等待事件处理器完成,但不清楚这在架构方面应该如何发生。

它是异步的、基于队列的 RPC(例如Rabbit RPC),还是有另一个侦听器在某处等待异步响应?

对于如何从架构的角度实现这一点有什么想法吗?

【问题讨论】:

【参考方案1】:

在我看来,他们只是没有绘制从事件处理器返回的事件,可能是因为它们可能不是特定的事件(例如某种回调),或者因为它们可能不是正常 em> 事件(可能是仅返回到中介者且对任何其他订阅者不可见的事件),具体取决于您用作中介者的内容。这部分似乎表明这样的事情:

事件中介可以通过多种方式实现。了解每个实施选项以确保您的解决方案 为事件调解器选择符合您的需求。

事件中介的最简单和最常见的实现是 通过 Spring Integration 等开源集成中心, Apache Camel 或 Mule ESB。这些开源中的事件流 集成中心通常通过 Java 代码或 DSL 实现 (特定领域的语言)。对于更复杂的调解和 编排,可以使用BPEL(业务流程执行语言) 再加上一个 BPEL 引擎,例如开源 Apache ODE。 BPEL 是 一种标准的类似 XML 的语言,用于描述数据和步骤 处理初始事件所需的。对于非常大的应用程序 需要更复杂的编排(包括步骤 涉及人机交互),您可以实现事件中介 使用业务流程管理器 (BPM),例如 jBPM。

了解您的需求并将其与正确的活动相匹配 调解器的实施对于任何事件驱动的成功都至关重要 使用这种拓扑的架构。使用开源集成中心 做非常复杂的业务流程管理编排是一个 失败的秘诀,就像实施 BPM 解决方案一样 简单的路由逻辑。

他们提到 Spring 作为一种可能的实现 - 我从未使用过它,但查看文档 (here) 我看到了回复通道的概念:

...当服务方法返回非空值时,端点将尝试将回复消息发送到适当的回复通道。


目标是发送一条或多条消息以异步处理,然后在结果返回时发送其他消息。我认为这些结果如何返回(函数回调、“响应”事件、Web API 调用等)在模式级别并不重要——这取决于您的特定基础架构。

对我来说,这听起来有点像 Saga 模式 (link)。在这种情况下,Saga(或 Mediator)知道完成某些任务所需的步骤,并维护有关该任务进度的某种状态。

它触发要处理的命令并监听响应。当响应(事件)到来时,它会更新其状态,然后使用其状态来确定接下来需要触发哪些命令。

这种情况一直持续到 A) 流程完成,或 B) 流程中的某个步骤失败(在这种情况下,它可能会反转方向并开始触发补偿命令以“撤消”先前的操作)。

使用您引用的帖子中的下图,传奇/调解人的“想法”可能是...

    重定位事件,因此触发更改地址命令并等待。 收到地址更改事件。现在我已经更改了地址,但我还没有重新计算报价或更新声明,所以我将把它们发送出去(它们不冲突,所以把它们都发送出去)然后等待。 收到ClaimsUpdated 事件。在继续之前仍需要重新计算,所以请继续等待。 收到QuoteRecalced 事件。现在我已经更新了地址、重新计算了报价并更新了索赔,我可以发送 Adjust Claims 命令,然后等待。

...等等。

您可能想要添加持久性(这样它可以在发生崩溃时从中断的地方继续)、幂等事件处理器(因此重播事件不会导致问题)和/或超时(不如果响应事件丢失/丢失,则永远等待)。

【讨论】:

【参考方案2】:

我想你在图表本身上就有答案了:

初始事件步骤(红色)是关键。每个事件处理器都会产生一个事件,该事件进入事件队列,然后进入事件中介。

架构是事件驱动和异步的。单个事件队列处理事件调解器的路径。而且由于这是将事件传入事件中介者的唯一方法,显然,任何想要向中介者发送事件的东西都需要使用这条路径。

在某个时间点,在某个事件之后,事件中介器将声明操作成功完成,并且不会向事件处理器分派更多事件。

虽然,我必须说,你是对的,这在文章中没有明确说明。我认为这将在他们正在预览的书中得到更好的说明。

【讨论】:

以上是关于关于事件驱动拓扑中的中介者的主要内容,如果未能解决你的问题,请参考以下文章

spring事件驱动模型--观察者模式在spring中的应用

180609-Spring之事件驱动机制的简单使用

事件驱动的缓冲与定时器驱动的缓冲[封闭式]。

同步异步事件驱动

libevent 中的应用程序驱动事件

jQuery中的事件与驱动