作者:罗静
在刚刚曩昔的RocketMQ Summit 2022 全球开发者峰会上,咱们对外正式开源了咱们的新产品 RocketMQ-Eventbridge 事情驱动引擎。
RocketMQ 给人最大的形象一向是一个音讯引擎。那什么是事情驱动引擎?为什么咱们这非必须推出事情驱动引擎这个产品?他有哪些运用场景,以及对应的技能计划是什么?
今日咱们就一同来看下,整篇文章包含三部分:
榜首部分,咱们一同看下什么是事情。
第二部分,和咱们一同看看,事情有哪些纷歧样的“超能力”,运用这些“超能力”呢,咱们又能干些什么?
第三部分,咱们讲一下 RocketMQ 给出的关于事情的解决计划,也是咱们这次开源的项目:RocketMQ-EventBridge。
什么是事情
咱们自己能够先在脑袋里想一下,什么是事情?咱们给事情下的一个界说是:
曩昔现已发生的事,特别是比较重要的事。
A thing that happens, especially one of importance.
这个很好了解。比方说,昨天下午我做了一次核酸检测;今日上午又吃了一个冰激淋。这些都是曩昔现已发生的事情。可是,假如我再问:事情跟音讯有什么区别?这个时分,咱们是不是觉得事情这个界说,好像又不那么清晰?
方才说的那些事情,是不是也能够了解为音讯啊?假如,老张给我发送了一条短信,这个算是事情,还是音讯啊?平常开发进程中,“什么时分运用音讯,什么时分运用事情?”
不过,在答复这个问题之前,咱们一同来看一个典型的微服务。
一个微服务体系和外部体系的交互,能够简略分为两部分:一是接纳外部恳求(便是图中上面黄色的部分);二是是调用外部服务(便是图中下面绿色的部分)。
接纳外部恳求,咱们有两种方法:一种是供给 API,接纳外部发过来的 Query 恳求和 Commond 恳求;别的一种是自动订阅外部 Command 音讯。这两类操作,进入体系内部之后呢,咱们常常还会,调用其他为微服务体系,一同协同处理,来完结一个具体的操作。当这些操作,使得体系状况发生改变时,就会发生事情。
这儿呢,咱们把从外部接纳到的 Command 音讯,和体系内部发生的事情,都称之为音讯。
咱们总结一下,音讯和事情的关系是这样的:音讯包含两部分,Command 音讯和 Event 音讯
1、看图中左半部分,Command 是外部体系发送给本体系的一条操作指令;
2、再看图中右半部分,Event 则是本体系收到 Command 操作恳求,体系内部发生改变之后,随之而发生了事情;
所以,事情和音讯是不同的,事情能够了解为是一种特殊的音讯。其特殊的点,首要在 4 个当地:
已发生、且不行变
事情,必定是“已发的”。“已发生”的代表什么呢?不行变的。咱们不行能改变曩昔。这个特性十分重要,在咱们处理事情、剖析事情的时分,这就意味着,咱们肯定能够相信这些事情,只要是收到的事情,必定是体系实在发生过的行为。而且是不行修正。
对比 Command 和 Query。Command 的中文是什么?指令。很显然,它是还没有发生的,仅仅表达了一种期望。咱们知道“期望的”,纷歧定会成功发生。
比方:把厨房的灯翻开、去按下门铃、转给 A 账户 10w……
这些都是 Commond,都是期望发生的行为。可是,最终有没有发生?并不知道。
Event 则是清晰现已发生的事情。比方:厨房灯被翻开了、有人按了门铃、A 账户收到了 10w……
再对比 Query,它则是查询体系当前状况的一种恳求,比方:厨房的灯是翻开着的、门铃正在响、查下账户显现余额 11w……
无期望的
这个怎样了解?事情是客观的描绘一个事物的状况或特点值的改变,但关于怎样处理事情自身并没有做任何期望。
相比之下,Commond 和 Query 则都是有期望的,他们期望体系做出改变或则返回成果,可是 Event 呢,它仅仅客观描绘体系的一个改变。
咱们看一个比如:交通信号灯,从绿灯变成红灯,事情自身并没有要求行人或汽车禁止通行,而是交通法规需求红绿灯,并赋予了其规矩。
所以,体系一般不会定向的、单独向别的一个体系发送事情,而是一致的告知“事情中心”,“事情中心”呢,那里边有各个体系上报上来的,林林总总的事情。体系会向事情中心说明:自己这个体系,会发生哪些事情呀,这些事情的格局是怎样样的呀。
别的体系假如感兴趣呢,就能够来自动订阅这些事情。真正赋予事情价值的,是事情顾客。事情顾客想看看,某个体系发生了什么改变呀?OK,那他就去订阅这些事情,所以事情是顾客驱动的。
这跟音讯有什么区别呢?Commond 音讯的发送和订阅,是两头约好好的,外人不知道,往往是以文档或代码的方法,咱们按约好好的协议,发送和订阅消费,所以音讯是生产者驱动的。
咱们打个比方,事情就像市场经济,产品被生产出来,具体有什么价值,有多大价值,很大程度上看其顾客。咱们能看到体系中各式各样的事情,就像橱窗里摆放了各式各样的产品。而 Commond 音讯呢,有点像计划经济,一出生就带着很强的目的性,我便是要“分配”给谁消费。
天然有序
事情的第三个特性是:“天然有序”。意义:同一个实体,不能一起发生 A 又发生B,必有先后关系;假如是,则这两个事情必归于不同的事情类型。
比方:针对同一个交通信号灯,不能既变成绿灯,又变成红灯,同一时间,只能变成一种状况。
咱们或许发现了一点,这儿其实躲藏了事情的一个额定特点:由于天然有序,跟时间轴上的某一时间强绑定,且不能一起发生,所以它必定是仅有的。
假如咱们看到了两个内容一样的事情,那么必定是发生了两次,而且一次在前,一次在后。(这关于咱们处理数据最终一致性、以及体系行为剖析都很有价值:咱们看到的,不光光是体系的一个最终成果,而是看到变成这个成果之前的,一系列中心进程)
具像化
事情的第四个特性是:“具象化”的。
事情会尽或许的把“案发现场”完好的记录下来,由于它也不知道顾客会怎样运用它,所以它会做到尽量的翔实,比方:
●是由谁发生的事情?Subject
●是什么类型的事情?Type
●是谁发送的事情?Source
●事情的仅有性标志是什么?Id
●什么时分发生?Time
●事情的内容是什么?Data
●事情的内容有哪些信息?Dataschema
咱们还是以交通信号灯举比如:
对比咱们常见的音讯,由于上下流一般是确认的,常常为了功能和传输功率,则会做到尽或许的精简,只要满意“计划经济”指定组织的顾客需求即可。
总结一下,事情上面的 4 个特性,是对事情巨大的一个特点加成,让事情拥有了跟普通音讯纷歧样的“超能力”。使事情,常常被用到 4 个典型场景:事情告诉、事情溯源、体系间集成和 CQRS。
下面让咱们一个个打开,具体看看这些运用场景。
事情的典型运用场景
事情告诉
事情告诉是咱们体系中很常见的一个场景。比方:用户下单事情告诉给支付体系;用户付款事情告诉给生意体系。
这儿,让咱们回到一开始信号灯那个比如。当交通信号灯,从红灯变成绿灯时,或许存在许多体系都需求这个信息。
方法 1:发送方自动调用,适配接纳方
一种最简略的方法是,咱们依次 call 每个体系,并把信息传递出去。比方:信号灯体系,自动调用地图导航的 API 服务、调用交警中控的 API 服务,调用城市大脑的 API 服务,把红绿灯改变信号发送出去。
但咱们都知道,这个规划十分糟糕。特别当体系越来越多时,这无疑是灾难的,不只开发本钱高,而且其间一个体系出现问题,或许会 hang 住整个服务,则导致调用其他体系都会受到影响。
方法 2:接纳方自动订阅,适配发送方
一个很自然的解决计划是,咱们将这些信息发送到中心音讯服务 Broker,其他体系假如有需求,则自动去订阅这些音讯即可。
这个时分,信号灯体系与其他体系并没有直接的调用依靠,交警中控服务、地图导航服务、城市大脑服务,只要依照约好的协议,去订阅信号灯的音讯,并解析这些信息即可。
可是,这儿相同存在一个问题:这个架构中,是以“信号灯”为中心。顾客需求了解发送者的事务范畴,并自动增加适配层,(便是图中白色回旋镖部分),将音讯转化为自己事务范畴内的言语。但关于每一个微服务来说,他都期望都是高内聚低耦合的。
假如交警中控需求全国的信号灯数据,可是每个地域的音讯格局又纷歧样,这就意味着,交警中控需求适配每一个地域的协议,做一层转化。而且万一后面改变了怎样办?想想就知道这个运维本钱有多可怕。
那是否交警中控体系,能够要求全国一切红绿灯体系,都按同一种数据协议给到自己呢?不好意思,这些信号灯数据地图服务也在用,城市大脑也在用,不能更改。
方法 3:引入事情,Borker 依据接纳方协议,进行灵敏适配
但假如运用事情,就纷歧样了。由于事情是“无期望的”,“具像化的”,天然的保存了案发现场尽或许多的信息,且更加规范规范,关于顾客(也便是交警中空)来说,能够简单将不同省份,搜集上来的事情,简单拼装成,契合自己事务要求的格局。
而且,这一拼装,是在中心层 Broker 发生的。关于交警中控来说,它只需求,依照自己事务范畴的规划,供给一个接纳事情的 API,然后其他事情,经过 Broker,自动投递到这个 API 上即可。自始至终,对交警中控体系,没有一行适配外部事务的代码。
所以,这种方法有 3 个明显的优势:
1、只重视自己事务范畴自身,不需求做适配外部的代码;
2、一切对体系的改变,收敛到 API,为仅有进口;同一个 API,或许既是用来接纳事情的,也或许一起用于控制台操作;
3、由于事情是推送过来的,所以,也不需求像之前一样,引入一个 SDK,和 Broker 发生连接,获取音讯,降低了体系的复杂度。
这样,咱们一开始的图,就会变成这个姿态:交通信号灯发生事情,投递到事情中心,其他需求这些事情的顾客,在事情中心订阅,再由事情中心,依照他们期望的事情格局,自动投递曩昔。
让咱们再来回忆下整个进程:
第 1 幅图:一开始,咱们经过强依靠的方法,让信号灯体系,自动将信息发送给各个体系。那这张图里,咱们是以各个下流服务为中心,信号灯体系去适配各个下流服务。
第 2 幅图:后来,咱们采用传统音讯的方法,对调用链路进行了解耦,两头体系不再直接依靠了,可是依旧会存在事务上的依靠。顾客需求去了解生产者的音讯格局,并在自己体系内部,进行转化适配。所以,这儿其实是以生产者为中心。
第 3 幅图:最终,咱们引入了事情告诉的方法,关于这种方法,生产者和顾客,他们都只需求重视自己体系自身就能够了。生产者,生产什么样的事情,顾客,消费什么样的数据格局,都各自以自己的事务为中心,不需求为对方做适配。真正做到咱们说的高内聚低耦合,完成完全的完全解耦。
现在,回到咱们一开始说到的典型微服务模型,关于有些场景,咱们就能够变为下面这种方法:对微服务的改变操作,一致收敛到 API 操作进口,去掉 Commond 音讯进口。收敛进口,关于咱们保护微服务,保障体系稳定性,常常十分有长处的。
事情溯源
事情溯源是什么?事情溯源简略了解便是让体系回到曩昔恣意时间。那怎样样,才能让体系能够回到曩昔呢?很简略,首要体系一切发生的改变,都得以事情的方法记录下来;然后,咱们就能够经过回放事情的方法,回到曩昔任何一个时间。
那为什么只要事情才能做这个事,其他普通音讯不行呢?这个还是要回到咱们方才说的几个事情特性:已发生不行变的、天然有序且仅有的、而且是十分具体具体的,完好的记录了事情的案发现场。所以,关于事情溯源这个场景,事情能够说是体系的一等一的公民。
举个比如:比方说,假如咱们能够完好地搜集路上的各种事情信息,包含信号灯、车量、天气、拥堵路况等等,那么,咱们就能够“穿越时间”,回到交通现场,从头做一次决策。比方,在才智交通场景,当咱们想去验证一个调度算法的时分,咱们就能够回放其时发生的一切事情,来重现现场。
咱们或许觉得这个很奇特,可是,其实咱们平常一向有触摸,咱们知道是什么吗?便是咱们常用的代码版别-管理体系,比方:github。
这儿有咱们或许会问,假如一个体系积赞了许多事情,想重放是不是得好久?比方在一些生意场景,每天都会发生大量的事情,那应该怎样处理呢?这儿呢,体系一般每天晚上都会打一份快照。假如体系意外宕机,想回到某一个时间,就能够把前一天的快照取出,然后再从头跑下当天的事情,即可康复。而白天呢,一切的事情都是在内存中进行处理,不会跟数据库交互,所以体系功能十分快,只要事情会落盘。
当然,事情溯源也不是合适一切场景,它有长处也有缺点,具体看上图。
体系间集成
方才讲的第1个场景:事情告诉,一般涉及到两个上下流团队的协作开发;讲的第 2 个场景:事情溯源,则一般是 1 个团队内的开发;但体系间集成,则往往面临的是三个事务团队的协作开发。这个怎样了解呢?
其实这个也很常见:比方公司里购买了 ERP 体系,一起也购买了外部考勤体系、外部营销体系服务等等。这些体系都有一个共同点,是什么?都不是咱们自己开发的,是而买来的。
假如咱们想把 ERP 体系的人员信息,实时且自动同步到考勤体系中去怎样办?其实这个是有点麻烦的,由于这些都不是咱们自己开发的。
1、咱们不能修正 ERP 体系的代码,自动去调用考勤体系,把人员改变信息发送曩昔;
2、也不能修正考情体系的代码,自动去调用外部 ERP 体系的 API;
可是咱们能够经过事情总线,借助 webhook 或则规范 API 等等方法,搜集上游的 ERP 体系发生的人员改变事情,然后进行过滤和转化,推送到下流考勤体系中去,当然,这儿也能够是内部自研服务。
所以,现在的研制形式变成了:事情中心管理了一切 SaaS 服务,包含内部自研体系发生的一切事情。然后呢,咱们只需求在事情中心,寻找咱们需求的事情,进行订阅,对 SaaS 服务和内部自研体系,进行简略服务编列,即可完结开发。
CQRS
CQRS 中的 C 代表 Command,Command 什么意思?便是明令,一般包含:Create/Update/Delete,Q 代表 Query,是指查询。所以 CQRS 本质是读写别离:一切的写操作,在图中左边的体系中完结,然后将体系由于 Command 发生改变的事情,同步到右边的查询体系。
这儿同学或许有疑问,这跟数据库的读写别离有什么区别?数据库读写别离也是供给一个写的 DB,一个读的 DB,两头做同步。对吧…
那这儿很大的一个区别是:关于数据库的读写别离,是以数据库为中心,两头的数据库是一模一样的,乃至数据的存储结构也是一模一样的。
可是关于 CQRS 的读写别离场景,是以事务为中心,两头存储的数据结构格局,往往是纷歧样的,乃至数据库都不是同一种。完全围绕各自的读写事务逻辑,规划最佳技能选型。关于写场景,为了保障事务,咱们或许运用关系性数据库;关于读的场景,咱们为了提高功能,咱们或许会运用 Redis、HBase 等 Nosql 数据库。
当然 CQRS 也不是合适一切场景,他往往比较合适:
●期望一起满意高并发的写、高并发的读;
●写模型和读模型差别比较大时;
●读/写比十分高时;
咱们方才讲了事情的 4 个运用场景,可是,事情不是万能的,就像软件研制也没有银弹,有许多场景也并不合适-运用事情。包含:
-
强依靠 Response 的同步调用场景;
-
要求服务调用坚持事务强一致性的场景。
RocketMQ 关于事情的解决计划
需求什么样的能力?
首要,依照之前讲到的事情运用场景,咱们整理下,假如咱们做好事情驱动这块,咱们的体系,需求具备什么样的能力呢?
榜首,咱们肯定得有一个事情规范,对吧…由于,事情不是给自己看的,也不是给他看的,而是给一切人看的。方才,咱们也讲到事情是无期望的,它没有清晰的顾客,一切都是潜在的顾客,所以,咱们得规范化事情的界说,让一切人都能看得懂,一目了然。
第二,咱们得有一个事情中心,事情中心里边有一切体系,注册上来的各种事情,(这个跟音讯纷歧样,咱们没有音讯中心,由于音讯一般是定向的,是生产者和顾客约好的,有点像计划经济,音讯生产出来的时分,带着很强的目的性,是给谁谁消费的。而事情有点像市场经济,事情中心呢,)这个有点类似市场经济大卖场,玲琅满目,里边分类摆放了各式各样的事情,一切人即便不买,也都能够进来瞧一瞧,看一看,有哪些事情,或许是我需求的,那就能够买回去。
第三,咱们得有一个事情格局,用来描绘事情的具体内容。这相当于市场经济的一个生意契约。生产者发送的事情格局是什么,得确认下来,不能总是变;顾客以什么格局接纳事情也得确认下来,不然整个市场就乱套了。
第四,咱们得给顾客一个,把投递事情到方针端的能力。而且投递前,能够对事情进行过滤和转化,让它能够适配方针端 API 接纳参数的格局,咱们把这个进程呢,一致叫做订阅规矩。
第五,咱们还得有一个存储事情的当地,便是最中心的事情总线。
事情规范
关于方才说到的榜首点事情规范,咱们选取了 CNCF 旗下的开源项目 CloudEvents,现在已被广泛集成,算是一个事实上的规范。
它的协议也很简略,首要规范了 4 个必选字段:id,source、type、specversion;以及多个可选字段:subject、time、dataschema、datacontenttype和data。上图右边,咱们有一个简略的比如,咱们能够看下,这儿就不具体打开了。
别的,事情的传输也需求界说一种协议,便利不同体系之间的沟通,默许支撑三种 HTTP 的传输方法:Binary Content Mode、Structured Content Mode 和 Batched Content Mode。经过 HTTP 的 Content-Type,就能够区分这三种不同的形式。其间前两种,都是传递单个事情;第三种则是传递批量事情。
事情 Schema
事情的 Schema,用来描绘事情中有哪些特点、对应的意义、约束等等信息。现在咱们选取了 Json Schema. 和 OpenAPI 3.0,依据事情的 Schema 描绘,咱们能够对事情进行合法性校验。,当然 Schema 自身的修正,也需求契合兼容性原则,这儿不作具体打开。
事情过滤和转化
关于事情的过滤和转化,咱们供给了 7 种事情过滤方法和 4 种事情转化方法,具体能够下图描绘:
技能架构
咱们 RocketMQ 围绕事情驱动推出的产品,叫做 EventBridge,也是咱们这非必须开源的新产品。
他的整个架构能够分为两部分:上面是咱们的控制面、下面是咱们的数据面。
控制面中最上面的 EventSource 是各个体系注册上来的事情源,这些事情能够经过 APIGateway 发送事情到事情总线,也能够经过装备的 EventSource,生成 SouceRuner,自动从咱们的体系中,去拉取事情。事情到达事情总线 EventBus 之后,咱们就能够装备订阅规矩了 EventRule,在规矩 EventRule 里咱们设置了事情怎样过滤,以及投递到方针端前,做哪些转化。体系基于创建的规矩会生成 TargetRunner,就能够将事情推送到指定的方针端。
那这儿 SouceRuner 和 TargetRunner 是什么呢?咱们具体能对接哪些上下流 Source 和 Target?
这些咱们都能够在下面的 SourceRegister 和 TargetRegister 提前进行注册。
所以 EventBridge 的数据面是一个开放的架构,他界说了事情处理的SPI,底下能够有多种完成。比方,咱们把 RocketMQ 的 HTTPConnector 注册到 EventBridge 中,那咱们就能够把事情推送到 HTTP 服务端。
假如咱们把 Kafka 的 JDBC Connector 注册到 EventBridge 中,咱们就能够把事情推送到数据库。
当然,假如你的体系不是通用的像 HTTP/JDPC 等协议,也能够开发自己的 Connector,这样就能将事情实时同步到 EventBridge,或则接纳来自 EventBridge 的事情。
除此之外,咱们还会有一些附加的运维能力,包含:事情追踪、事情回放、事情剖析、事情归档。
RocketMQ-EventBridge 与云上
在一切开源的,与其他上下流体系做集成的 Connector 当中,咱们有一个特殊的 Connector,叫:EventBridgeConnector,经过它能够便利的和阿里如此上的事情总线进行集成。这儿有两个典型的运用场景:
榜首个场景是:IDC 体系内部发生的事情,不只能够用来做内部体系间的解耦,还能够实时同步到云上,驱动云上的一些核算服务,比方经过云上 Maxcompute 对内部发生的事情进行离线剖析,或则驱动云上的图像识别服务,实时剖析事情中标注的图片。
第二个场景是:假如 IDC 内部运用到了自建 MQ,咱们相同能够经过 MQConnector 和 EventBridgeConnector,实时同步事情到云上,逐步将内部自建 MQ,迁移到云上MQ。
生态开展
关于 EventBridge 的未来方向,咱们期望是在开源,构建一个支撑多云架构的事情总线生态。这个怎样了解?简略来说,咱们期望在不同云厂商之间,包含云厂商和内部 IDC 体系之间,能够经过事情,来打破围墙,完成互通。尽管,这几年云核算开展很快,可是关于一些特别大的客户来讲,有时分并不期望跟某家云厂商强绑定。这不光是市场充分竞争的成果,也是大客户一种降低危险的手段。所以,这个时分,怎样在不同云厂商之间,包含云厂商体系和自己内部 IDC 体系之间,灵敏的交互,乃至灵敏的迁移,是企业十分重要的一个诉求。
当然,完成这个是有必定难度的。不过假如咱们在进行企业架构规划的时分,是基于事情驱动架构进行规划开发——不同体系之间的交互,围绕事情打开,就会简单许多。
事情,在这儿,就好比一种通用言语,经过这个通用言语,就能够完成和不同体系之间的沟通交流。比方:用 IDC 体系内部的事情,去驱动阿里云上服务;乃至用阿里云上的事情,去驱动 AWS 上的服务运转;
为了完成这个方针,咱们在和不同云厂商,不同 SaaS 体系服务商,进行体系间集成的时分,需求开发与之对应的连接器。
也欢迎咱们,一同来共建 RocketMQ-EventBridge 的生态。
源码地址:
github.com/apache/rock…
感兴趣的小伙伴们能够扫描下方二维码加入钉钉群评论(群号:44552972)
点击此处,进入 EventBridge 官网了解更多信息~