作者 | 六翁
以 Kubernetes 为基础设施的云原生技术,彻底改变了我们的开发和思维模式。事件作为云原生领域的一等公民,已经无处不在,是云原生架构体系松耦合、灵活性的基础。
作为 Gartner 定义的 10 大战略技术趋势之一,事件驱动架构(EDA)逐渐成为主流技术架构。根据 Gartner 的预估,到 2022 年,在新型数字化商业的解决方案中,将有 6 成使用 EDA,在商业组织参与的技术栈中,EDA 有一半的占比。
本文将介绍事件、事件驱动架构、阿里云事件驱动引擎 EventBridge 及其在事件的标准化、中心化、事件驱动架构上的能力。
事件及事件驱动架构
1、事件
事件是已经发生的事实,并且是不可变的。相比而言,消息是一个服务为了另一个服务的消费或存储而生产的原始数据,消息是可以被修改的。
事件的生产者如实地产生和投递事件,它不关心这个事件将由谁、因何,以及怎样去处理。而消息的生产者是知道谁来消费的,并且知道封装哪些因素到消息中,以便消费者处理。
事件的 Broker 被设计为提供事实日志。事件在超时时间后被删除,这个超时时间是由组织或者业务定义的。而消息的 Broker 被设计为处理各类问题的,当消费者感知到消息后,消息即可被删除。
事件 | 消息 | |
Data | 已经发生的事实,并且不可变(Immutable) | 为消费或存储而生产的原始数据 |
Producer/Consumer | 生产者不知道消费者是谁以及如何处理 | 生产者知道消费者是谁以及如何处理 |
Broker | 提供事实日志 超时时间后,事件被删除 |
处理各类问题 被消费者感知后,消息被删除 |
- 离散事件:描述状态(state)的变化 可执行的
- 连续事件:描述处于怎样的状态(condition) 可分析的
通常,事件是离散的,用于描述一个事物的状态变化,可以被执行。消费者根据离散事件所描述的状态,执行相应的动作。
事件也可以是连续数据流中的一部分,用来描述一个事物当前处于某种状态下。这些连续的事件是可分析的,消费者可以根据这些状态的变化,分析出某种趋势及背后的原因。
事件应当被设计为最小尺寸、最简类型、单一目的。这里要着重介绍下 CloudEvents。CloudEvents 在 2018 年 5 月进入 CNCF 基金会的沙箱项目,然后只用了1年多时间就成为 CNCF 的孵化项目,其发展速度非常快。CloudEvents 将会成为云服务之间,事件通讯的标准协议。同时要强调的是,CloudEvents 已经发布了多个消息中间件的绑定规范。
CloudEvents
- 2017 年 12 月 启动
- 2018 年 05 月 CNCF 沙箱项目
- 2019 年 10 月 1.0 CNCF 孵化项目
- 2020 年 12 月 1.0.1
2、事件驱动
事件驱动架构是一种围绕着事件的生产、探测、消费,及响应的软件架构范式。为云原生应用的分布式和伸缩性,提供了基础保证。事件驱动架构天然的异步特性,使云原生应用在设计上,可以根据 DDD 理论,清晰地划分出服务间的上下文边界,优雅地实现松耦合。
1) 事件的传递模式
我们走近事件驱动,来看一下事件的传递模式。与请求驱动不同,事件驱动的两端不是直连的。
事件的传递模式包含如下三种。
基于队列的生产者-消费者模式。这是一种单一接收者的模式,用于两个服务之间的事件传递。生产者服务并不关心消费者服务如何处理事件。
基于队列的异步请求-回调模式。这种模式和请求驱动的 request-response 类似,是异步的 request-reply 或者叫 request-callback,同样用于两个服务之间的事件传递。生成者服务会关心消费者服务随后生产的响应事件。
基于主题的发布者-订阅者模式。这是一种多对多的模式。发布者服务可能生产不同类型的事件,并将其传输给不同的主题,订阅者服务可能订阅一个或者多个主题,以实现对不同类型事件的处理。
2) 事件的服务定义模式
我们再来了解下事件的服务定义模式。
我们已经知道,事件的生产者并不知道消费者是谁,因此不能像消息那样预先定义消息的格式。因此,在事件驱动架构中,需要一个 Schema Registry 为生产者提供序列化依据,为消费者提供反序列化依据。
Schema 类似 gRPC 中的 proto 定义。在请求驱动模式下,gRPC 的服务端和客户端会分别根据 proto 定义,生成 stub 模板代码。然后将模板代码提供给自己的上层代码调用,从而实现序列化和反序列化。
与之类似,在事件驱动模式下,消费者在获取事件后,可以根据 CloudEvents 标准协议,解析出 Schema 和 Content(通常是二进制),然后通过消费者调用 Schema Registry 服务,将 Content 反序列化为事件体。
可以看到,事件的服务定义模式,可以将事件的生产者和消费者充分地解耦。
3、EventBridge
通过上面的介绍,相信你已经对事件和事件驱动的概念有了较清晰的认识。接下来我介绍下 EventBridge。
EventBridge 是为用户提供构建松耦合、分布式的事件驱动架构的 Serverless 事件总线服务。EventBridge 的事件传输和存储遵循 CloudEvents 协议。
在 EventBridge 中,事件的生产者称为事件源,传输和存储事件的介质称为事件总线,事件的消费者称为事件目标。事件由事件规则转换、匹配、聚合,并路由到事件目标。
EventBridge 连接了事件生产和消费的两端,利用云原生基础设施的能力及 Serverless 按需消费的特点,为用户提供了低代码、松耦合、高可用的事件处理能力。用户可以以极简的投入,实现强响应能力的 EDA 云原生应用。
同时,EventBridge 基于标准的事件协议,有利于促进各类事件源的事件标准统一,使事件孤岛逐步融合进完整的事件生态体系之中。因此,EventBridge 正成为云原生事件驱动架构的标准范式。
那么,EventBridge 是如何结合 Serverless 实现极简的 EDA 应用的呢?在接下来的事件总线范式及应用场景中,我将会详细介绍。
事件总线
EventBridge 的一大特点是标准事件协议的管道。那么,我们一起来看一下,阿里云事件总线 EventBridge 实现这个管道能力的各个组成部分。
1、EventBridge的组成
1)事件源
阿里云 EventBridge 的事件源包罗万象。可以是阿里云的各类云产品、阿里云第三方SaaS 服务,也可以是阿里云用户自己的服务,甚至可以是其他云厂商、边缘服务、私有机房内的服务。用户使用 CloudEvents 的 SDK,即可将事件推送到阿里云事件总线,从而实现事件上云。
2)事件总线
为了提供开箱即用的云产品事件处理能力,阿里云 EventBridge 为每个用户提供了租户隔离的默认事件总线。用户所使用的云产品产生的事件,会由这条事件总线传输和存储。
用户可以通过自定义事件总线对接各类事件源,将不同的数据源产生的事件统一采集、存储和响应。
3)事件规则
EventBridge 的事件规则的两端分别是事件总线和事件目标。用户通过配置匹配规则、转换规则等,以低代码甚至无代码的方式,实现从事件总线到事件目标的事件过滤、转换和路由。
4)事件目标
事件目标是事件被最终处理的地方。阿里云 EventBridge 目前已经支持了多种事件目标,为用户带来开箱即用的体验。我们可以为一个告警事件指定钉钉机器人,可以将一个订单事件通过 HTTP 网关传输给用户服务,也可以将事件投递给消息服务实现事件上云。
当然,云原生的经典事件目标是由 Serverless 服务,因为 Serverless 服务充分展现了云原生的优势。
- Serverless 的资源是按需消费的,将弹性发挥到极致
- 轻量级的函数具有低延迟、高可用的能力,且无运维成本
- 用户编写事件处理函数的学习门槛低、开发代码量小
5)举个例子
我这里给大家展示个小例子,一起感受下 EventBridge+Serverless 实现 EDA 的轻量化。
首先我们自定义一个事件总线,将 Kubernenets 容器服务作为事件源,将 Serverless 服务(函数计算)作为事件目标。
然后我们为容器内的资源状态变化事件定义一个事件规则,当这类事件进入事件总线后,将被路由到函数计算服务。
最后,我们编写并部署一个处理这类事件的函数到函数计算服务,在函数内,首先接收到 CloudEvents 标准协议的事件,通过 Schema Registry 解析事件,最后由函数自身完成事件处理——比如调用容器服务的 API,对资源进行相关操作。
从这个小例子中,我们可以看到,EventBridge+Serverless 可以让用户以很低的成本快速实现一个事件驱动的业务。四两拨千斤。
接下来,我将介绍两种事件驱动架构的编排模式,并给出相应的例子,抛砖引玉,希望能激发你的脑洞,结合自身业务,得到因地制宜的事件总线最佳实践。
2、事件驱动架构的编排模式
1)调停者模式
对于处理较复杂的事件驱动场景,调停者模式能帮助我们有条不紊地对事件进行拆解和分析,并最终执行指定的动作。调停者模式由三个角色组成:外部服务、调停者、执行者。
首先,外部服务作为一个事件总线的事件源,将事件传输给事件总线。作为调停者的微服务或者函数是这个事件总线的事件目标,接收并处理来自某个事件源的事件。
调停者函数在执行过程中,会将事件处理的多个中间状态作为新的事件,传输到对应的事件总线。此时,调停者是作为这些事件总线的事件源。作为执行者的函数是这些事件总线的事件目标。这些函数从事件总线中接收并处理事件,然后产生一个回调事件并传输到相应的事件总线中。可以看出,这里调停者和执行者之间,是前面讲到的异步请求-回调模式。
调停者接收到回调事件后,执行调停逻辑,并将结果作为回调事件,经过事件总线,传输给外部服务。
2)示例:智能家居
接下来,我来展示一个使用调停者模式实现智能家居的例子。
在这个例子中,我们将 IoT 设备/传感器作为外部服务,将用户的全屋系统作为调停者,将用户在函数计算中创建的函数作为执行者。
首先,传感器产生一条"空气质量超标"事件,并将其传输到用户自定义的"空气质量"事件总线。
用户的全屋系统接收到这个事件后,分别计算室内外空气质量,得出室外空气超标,然后将窗内外空气质量事件发送到用户自定义的"窗内外空气"事件总线,窗户控制函数作为执行者,向 IoT 服务发出关窗指令,然后传输窗户状态事件。
全屋系统得知窗户都已关闭后,继续根据用户定义的全屋逻辑,向新风控制、灯控等对应的事件总线发送相应的事件,以完成全屋控制。
调停者模式的示例就介绍到这儿。接下来,我来介绍管道和过滤器模式。
3)管道和过滤器模式
管道和过滤器模式由三个角色组成:源服务、管道函数、目标服务。
源服务产生的事件,经历多个事件总线,被相应的管道函数执行转换、过滤、聚合等操作,最终将新的事件,经事件总线传输给目标服务。
4)示例:在线学习
接下来,我来展示一个使用管道和过滤器模式实现人工智能服务在线学习的例子。
我们都知道,AI 的兴起源自大数据。我们今天所使用的各类人工智能服务,背后都有一个或多个业务算法模型。这些模型通常是由算法架构+离线的、批量的大数据反复训练而成的。由于这些服务具有天然的数据相关性,因此实时发生的在线数据会对模型的改进有一定的帮助。
这里,我们假定出行推荐系统为源服务,出行模型训练服务为目标服务,中间的各个函数为管道函数。出行推荐系统将实时的路况事件传输到实时交通事件总线。
实时交通事件总线的事件目标是两个功能不同的函数。
- 第一个函数负责完成数据清洗和特征提取,然后生成特征事件,传输到特征事件总线。
- 第二个函数负责数据标注,将原始数据打标后,生成标注数据事件,传输到标注数据事件总线。
特征数据事件总线的事件目标同样是两个功能不同的函数。这里不再冗述。
最终出行模型训练服务会根据实时数据,训练出一个新的模型。这里省去了模型回归等工业化流程细节。
事件中心
到这里,我们对 EventBridge 作为事件传输、存储和路由的管道能力有了一定认识。接下来,我将介绍 EventBridge 的另一大特点,事件的中心化查询、展示、分析能力。
如前所述,EventBridge 基于标准的事件协议 CloudEvents,正逐步将事件孤岛统一、融合到一起,形成完整的事件生态体系。
在这个生态体系下,事件中心将用户使用的云产品、第三方 SaaS 服务、用户服务、云下服务所产生的事件统一到一起,为用户提供全方位的事件查询、可视化和分析能力。
- 事件中心以租户维度,为用户提供一个或者多个事件总线的查询和分析。
- 针对事件特征鲜明的服务或者云产品,事件中心提供了大盘和图表,方便用户实时观测。
- 同时,事件中心提供了事件告警和事件卡片,实现用户以0代码的方式处理特定的事件。
事件中心让事件的价值最大化,从事件角度为用户的云原生服务提供可追踪、可度量、可观测性。
展望
阿里云事件总线 EventBridge 作为云上的事件枢纽,最核心的能力是连接。无论是在线业务场景、IoT 场景、还是大数据场景,无论是阿里云、其他云厂商,还是私有 IDC 机房,我们都将提供安全可靠的集成方式。
未来,EventBridge 会重点发展生态网络。云时代下这么庞大的神经中枢系统,不是一日可以建成的,我们需要并期待与你一起共建云原生事件驱动架构生态。
﹀
﹀
﹀
搜索钉钉群号 31704055 加入技术交流群,
可获取云原生详细解决方案资料与专家答疑。