跳到主要内容
版本: 5.0

RocketMQ EventBridge 概览

RocketMQ EventBridge 致力于帮助用户构建高可靠、低耦合、高性能的事件驱动架构。在事件驱动架构中,微服务无需主动订阅外部消息,而是可以将微服务系统内触发变化的所有入口集中到 API,只需要关注当前微服务自身的业务领域模型定义和 API 的设计,而无需通过大量的胶水代码去适配和解析外部服务消息。EventBridge 负责将外部服务产生的事件安全可靠地适配并投递到当前微服务设计的 API。

什么时候我们用 RocketMQ 消息,什么时候我们用 EventBridge 事件?事件的含义是什么,与消息又有什么区别呢?

消息与事件

我们对事件的定义如下

Events refer to things that have already happened, especially important things.

事件和消息的关系如下:

image

消息包括 Command 消息和 Event 消息。Command 消息是外部系统发送给本系统的操作指令(如图左部分所示);Event 消息是系统收到 Command 操作请求后,内部发生变化后产生的事件(如图右部分所示);

事件的四个特点

1. 已发生

事件总是“已发生”的。“已发生”也就意味着它是不可变的。这个特点非常重要,当我们在处理事件和分析事件时,意味着我们可以绝对信任这些事件,只要收到事件,它就一定是系统真实的行为。

Command 代表的是一个操作请求,是否真实发生无法得知。例如:

* Turning on the kitchen lights
* Someone pressed the doorbell
* Account A received 100,000.

事件是一个明确的、已经发生的事情,例如

* The kitchen light being turned on
* Someone pressing the doorbell
* Account A receiving 100,000

2. 无预期

An event is an objective description of a change in the state or attribute value of a thing, but it does not make any expectations about how to handle the event itself. In contrast, both Command and Query have expectations, they hope the system will make changes or return results, but the Event is just an objective description of a change in the system.

例如:交通信号灯,从绿变黄,它只描述了一个客观事实,本身不带任何客观预期。在不同国家和地区,对这个事件赋予了不同的预期。例如日本黄灯等同于红灯,而在俄罗斯闯黄灯却是被容忍的。

相比于 Command 消息:

  • 事件:有点像“市场经济”,商品生产出来后,摆在商场的大橱窗里,消费者觉得好就买回去,如果没有人买,商品可能就过期浪费了。
  • Command 消息:有点像“计划经济”,按需生产,指定分发对象,浪费少。

3. 自然有序且唯一

The same entity cannot have both A and B occur at the same time, there must be a temporal relationship; if so, these two events must belong to different event types.

例如:对于同一个信号灯,不可能同时亮绿灯和红灯,它在某一时刻只能变成一种状态。如果我们看到两个内容完全相同的事件,那么它一定是发生了两次,并且有先后顺序。这对于数据一致性处理和系统行为分析(例如 ABA 场景)非常有价值:我们不仅看到了系统的最终结果,还看到了导致该结果的中间过程。

4. 具体化

事件会尽可能完整地记录“案发现场”,因为事件并不知道消费者会如何使用它们,所以会尽可能详细。包括

When did the event occur?
Who generated it?
What type of event is it?
What is the content of the event? What is the structure of the content?
... ...

相比于我们常见的消息,由于上下游一般已确定,通常为了提高性能和传输效率,消息会尽可能简洁,只要满足“计划经济”指定的消费方需求即可。

RocketMQ EventBridge 的典型应用场景

场景 1: 事件通知

在微服务中,我们经常遇到在一个微服务中产生的消息需要通知其他消费方的情况。这里我们对比三种方式

A: 强依赖方式

生产方主动调用消费方的微服务,并适配消费方的 API。这种设计无疑是非常糟糕的,生产方强依赖消费方,深度耦合。如果对某个消费方的调用出现异常,又没有做有效隔离,则很有可能导致整个微服务挂掉。当新的消费方接入时,这种方式也非常差。

B: 半解耦方式

生产方将消息发送到消息服务,消费方订阅消息服务获取消息,并将消息转化为自身业务领域模型所需的数据格式。这种方式在调用链上实现了解耦,大大降低了系统风险,但是对于消费方而言,它仍然需要理解和解析生产方的业务语义,并将消息转化为自身业务领域所需的格式。在这种方式下,当消费方需要订阅多个生产方的数据时,需要大量的胶水代码来适配生产方产生的每一个消息。此外,当上游生产方的消息格式发生变化时,也存在风险和运维成本。

C: 完全解耦方式

在这种方式下,消费方无需引入 SDK 来订阅 Broker,只需要根据自身业务领域模型设计 API,消息服务会过滤和转换上游

image

场景 2: 跨系统集成

场景 1 主要关注单个产品内部微服务之间的事件通信。场景 2 主要关注多个产品之间的事件通信。在一个企业中,我们经常使用多个产品,其中许多产品可能不是我们自己开发的,而是作为外部 SaaS 服务购买的。在这种情况下,很难让事件在不同的外部 SaaS 产品之间流动,因为这些外部 SaaS 产品不是我们自己开发的,并且不容易修改其代码。EventBridge 提供的事件中心能力可以帮助收集各种产品产生的事件并对其进行良好组织和管理,就像百货商店橱窗里的商品一样,精心布置并配备说明,供消费者选择,同时还提供送货上门服务。

image

RocketMQ EventBridge 如何工作?

为了解决上述两种场景中提到的问题,EventBridge 从五个方面入手

1. 确定事件标准

因为事件不是为了自己,而是为了大家。它没有明确的消费方,所有都是潜在的消费方。因此,我们需要对事件的定义进行标准化,让大家都能看得懂,而且容易理解。目前 CNCF 下的 CloudEvent 已经逐步成为业界广泛认可的事实标准,因此我们选择 CloudEvent 作为 EventBridge 的事件标准。

2. 建立事件中心

事件中心包含了各个系统注册进来的所有事件。这就像我们上面提到的市场经济百货商店,里面有分门别类的各种事件,大家可以进来看看哪些事件可能是自己需要的,然后买回去。

3. 定义事件格式

事件格式是用来描述事件具体内容的。这等同于市场经济中的销售合同。生产方发送的事件格式必须是确定的,不能总变;消费方接收事件的格式也必须是确定的,否则整个市场就会乱套。

4. 订阅“规则”

我们需要赋予消费方将事件投递到目标端的能力,并在投递前对事件进行过滤和转换,使其能适配目标端 API 接收参数的格式。我们称这个过程为创建订阅规则。

5. 事件总线: 最后,我们还需要一个地方来存储事件,那就是图中中间的事件总线。

image