事件驱动架构模式是一种流行的分布式异步架构模式,用于生成高度可伸缩的应用程序。它具有很强的适应性,可用于小型应用以及大型复杂应用。事件驱动的体系结构由高度分离的单用途事件处理组件组成,这些组件异步接收和处理事件。

事件驱动的体系结构模式由两个主要拓扑组成,即介体和代理。当您需要通过中央中介协调事件中的多个步骤时,通常使用中介拓扑,而当您希望在不使用中央中介的情况下将事件链接在一起时,将使用代理拓扑。由于这两种拓扑结构的体系结构特征和实现策略不同,因此了解每个拓扑结构以了解哪种拓扑结构最适合您的特定情况非常重要。

中介拓扑结构

中介拓扑对于具有多个步骤并需要某种级别的业务流程来处理事件的事件非常有用。

例如,放置股票交易的单个事件可能要求您首先验证交易,然后检查该股票交易是否符合各种合规规则,将交易分配给经纪人,计算佣金,最后进行交易。那个经纪人。所有这些步骤都需要一定程度的协调来确定步骤的顺序以及哪些步骤可以串行和并行完成。

中介体拓扑中有四种主要类型的体系结构组件:事件队列,事件中介,事件通道事件处理器。事件流以客户端将事件发送到 事件队列开始,该事件队列用于将事件传输到事件中介器。该事件介体 接收初始事件,并通过发送附加异步事件编排该事件的事件通道 以执行该过程的每个步骤。监听事件通道的事件处理器从事件介体接收事件并执行特定的业务逻辑来处理事件。图2-1说明了事件驱动架构模式的一般中介拓扑。
事件驱动架构 - 图1

图2-1。事件驱动的体系结构中介拓扑

在事件驱动的体系结构中,通常有十几个到几百个事件队列。该模式未指定事件队列组件的实现; 它可以是消息队列,Web服务端点或其任何组合。

此模式中有两种类型的事件:初始事件处理事件。初始事件是调解器接收的原始事件,而处理事件是由调解器生成并由事件处理组件接收的事件。

event-mediator组件负责编排初始事件中包含的步骤。对于初始事件中的每个步骤,事件中介器将特定处理事件发送到事件通道,然后由事件处理器接收和处理该事件通道。值得注意的是,事件调解器实际上并不执行处理初始事件所必需的业务逻辑; 相反,它知道处理初始事件所需的步骤。

事件调解器使用事件通道将与初始事件中每个步骤相关的特定处理事件异步传递给事件处理器。事件通道可以是消息队列或消息主题,但消息主题最广泛地与中介拓扑一起使用,以便处理事件可由多个事件处理器处理(每个事件处理器根据接收的处理事件执行不同的任务)。

事件处理器组件包含处理处理事件所必需的应用程序业务逻辑。事件处理器是独立的,独立的,高度分离的体系结构组件,用于执行应用程序或系统中的特定任务。虽然事件处理器组件的粒度可以从细粒度(例如,计算订单上的销售税)到粗粒度(例如,处理保险索赔)而变化,但重要的是要记住,通常每个事件处理器组件应执行单个业务任务,而不是依赖其他事件处理器来完成其特定任务。

事件调解器可以以多种方式实现。作为架构师,您应该了解每个实现选项,以确保为事件调解器选择的解决方案符合您的需求和要求。

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

了解您的需求并将它们与正确的事件中介实现相匹配对于使用此拓扑的任何事件驱动架构的成功至关重要。使用开源集成中心进行非常复杂的业务流程管理编排是一种失败的方法,就像实施BPM解决方案来执行简单的路由逻辑一样。
为了说明调解器拓扑如何工作,假设您通过保险公司投保并决定搬迁。在这种情况下,可能会调用初始事件,例如重定位事件。处理重定位事件 所涉及的步骤 包含在事件介体中,如图2-2所示。对于每个初始事件步骤,事件介体创建处理事件(例如,更改地址,重新计算报价等等)将该处理事件发送到事件通道并等待处理事件由相应的事件处理器处理(例如,客户处理,报价处理等)。此过程将继续,直到处理完初始事件中的所有步骤。事件介体上的recalc引用和更新声明步骤上的单个条形表示这些步骤可以同时运行。

经纪人拓扑

代理拓扑与中介拓扑的不同之处在于没有中心事件中介; 相反,消息流通过轻量级消息代理(例如,ActiveMQ,HornetQ等)以链式方式分布在事件处理器组件上。当您具有相对简单的事件处理流并且您不希望(或不需要)中央事件编排时,此拓扑非常有用。
代理拓扑中有两种主要类型的体系结构组件:代理组件和事件处理器组件。代理组件可以是集中式或联合的,并包含事件流中使用的所有事件通道。代理组件中包含的事件通道可以是消息队列,消息主题或两者的组合。
事件驱动架构 - 图2

图2-2。中介拓扑示例

该拓扑结构如图2-3所示。从图中可以看出,没有中央事件 - 中介组件控制和编排初始事件; 相反,每个事件处理器组件负责处理事件并发布指示其刚刚执行的操作的新事件。例如,平衡股票组合的事件处理器可以接收称为股票分割的初始事件。基于该初始事件,事件处理器可以进行一些组合重新平衡,然后将新事件发布到称为重新平衡组合的代理,然后由不同的事件处理器拾取。请注意,有时事件处理器发布事件但未被任何其他事件处理器拾取。这在您开发应用程序或提供未来功能和扩展时很常见。
事件驱动架构 - 图3

图2-3。事件驱动的体系结构代理拓扑

为了说明代理拓扑如何工作,我们将使用与中介拓扑中相同的示例(受保人移动)。由于没有中央事件调解器来接收代理拓扑中的初始事件,因此客户流程组件直接接收事件,更改客户地址,并发出一个事件,表明它更改了客户的地址(例如, 更改地址 事件。在此示例中,有两个事件处理器对更改地址事件感兴趣:引用过程和声明过程。报价处理器组件根据地址更改重新计算新的自动保险费率,并将事件发布到系统的其余部分,以指示其执行的操作(例如,重新 报价事件)。另一方面,声明处理组件接收相同的更改地址事件,但是在这种情况下,它更新未完成的保险声明并将事件作为更新声明事件发布到系统 。然后,这些新事件由其他事件处理器组件拾取,并且事件链继续通过系统,直到针对该特定启动事件不再发布事件。
事件驱动架构 - 图4

图2-4。代理拓扑示例

从图2-4中可以看出,代理拓扑完全是关于执行业务功能的事件的链接。理解代理拓扑的最佳方法是将其视为接力竞赛。在接力赛中,跑步者拿着一根接力棒并跑一段距离,然后将接力棒交给下一名跑步者,依此类推,直到最后一名跑者越过终点线。在接力赛中,一旦跑步者将接力棒交给指挥棒,她就完成了比赛。代理拓扑也是如此:一旦事件处理器处理事件,它就不再涉及该特定事件的处理。

注意事项

事件驱动的体系结构模式是一种相对复杂的模式,主要是由于其异步分布式特性。实现此模式时,必须解决各种分布式体系结构问题,例如在代理或介体发生故障时远程进程可用性,缺乏响应性以及代理重新连接逻辑。
选择此体系结构模式时要考虑的一个考虑因素是缺少单个业务流程的原子事务。由于事件处理器组件高度分离和分布,因此很难在它们之间维护事务处理单元。因此,在使用此模式设计应用程序时,必须不断考虑哪些事件可以独立运行,哪些事件无法独立运行,并相应地规划事件处理器的粒度。如果您发现需要跨事件处理器拆分单个工作单元 - 也就是说,如果您使用单独的处理器来处理应该是不可分割的事务 - 这可能不是您的应用程序的正确模式。
也许事件驱动架构模式中最困难的一个方面是事件处理器组件合同的创建,维护和治理。每个事件通常都有一个与之关联的特定合同(例如,传递给事件处理器的数据值和数据格式)。使用此模式确定标准数据格式(例如,XML,JSON,Java对象等)并从一开始就建立合同版本控制策略至关重要。

模式分析

整体敏捷
评级:
分析:整体敏捷性是指能够快速响应不断变化的环境。由于事件处理器组件是单一用途的并且与其他事件处理器组件完全分离,因此通常将更改隔离到一个或几个事件处理器,并且可以在不影响其他组件的情况下快速进行更改。

易于部署
评级:
分析:总体而言,由于事件处理器组件的分离性,这种模式相对容易部署。代理拓扑往往比中介拓扑更容易部署,主要是因为事件中介组件与事件处理器有些紧密耦合:事件处理器组件的更改可能还需要更改事件中介,这两者都需要部署任何给定的变化。

可测性
评级:
分析:虽然单个单元测试并不过分困难,但它确实需要某种专门的测试客户端或测试工具来生成事件。此模式的异步性质也使测试变得复杂。

性能
评级:
分析:虽然由于所涉及的所有消息传递基础结构,实际上可能实现事件驱动的体系结构不能很好地执行,但通常,该模式通过其异步功能实现了高性能。换句话说,执行解耦的并行异步操作的能力超过了排队和出列消息的成本。

可扩展性
评级:
分析:通过高度独立和分离的事件处理器,可以在此模式中实现可伸缩性。每个事件处理器都可以单独扩展,从而实现细粒度的可扩展性。

易于开发
评级:
分析:由于模式的异步性以及合同创建以及代码中对于无响应的事件处理器和失败的代理的更高级错误处理条件的需要,开发可能有些复杂。

参考链接:https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/ch02.html