基于云原生CloudEvent实现服务目录

基于事件驱动的系统架构在日常的平台开发中早已司空见惯,通过消息队列进行事件的发送,然后分别构建对应的生产者和消费者。不过在传统的业务开发模式不同的事件会有不同的格式,不同的生产者生成出的事件格式也各不相同,消费者能消费的格式也是千差万别,本质上事件、生产者T x M G W K n _ @、消费者还是耦合的。那如何解决@ l A | t m .该问题呢?那就是我们今天要聊的ClouP j LdEvent。

CloudEvent简介

基于云原生CloudEvent实现服务目录
S @ $官网的CloudEvents描述中我们可以看出,CloudEvent本质上就是一个描述事件数据的规范。V 5 /所以对于CloudEvents的学习有的时候,我们更多的应该是取理解其设计规范,而不是其所呈现出的数据结构形态。就像大家去学tcp协议一样, 你不是去学的这个字段叫什么,而是要理解为什么会有这个字段,其解决的问题是什么。

如何解耦

对于CloudEvents的学习笔者采用自顶向下的方式来进行学习,即先去了解CloudEvents是如何在平l $ @ / ~台上进行事件、消费者、生产者的解耦,然后在去思考底层的相关字段的细节
基于云原生CloudEvent实现服务目录
一个事件的生命周= | I A 5 ; m期通常会包含生产、传输、消费三个环节,下面我们分别对这三个环节来进行介绍cloudevent与传统事件开发模式的区别。

事件生产

在传统的开发模式下不同的业务d s % 8 ~ l生产的的事件也各不相同,并且事件本身数据会相对较少,更多的是类似信号传递的角色,即通知后端服务某个类型事件发生了,然后由对应的系统构建事件的上下文数据,进行业务逻辑处理。而在Cloudevents中则更注重事件的一致性与完整性。
基于云原生CloudEvent实现服务目录
为了保证事件# ! O r D l可以被统一的分发、解析与处理,Cloudevents采用了类似分层的事件封装机制,即"事件协议"与"事件数据"两层。事件协议是指Cloudevent定义了底层事件的格式,即大家都按照一套标准的规范来进行事件的封装,这样事件就可以被统一的处理和分发。而事件专有的数据则存储在Z m .对应的数据字段里面

完整性是我个人的理解,即我们在CloZ f aud的环境中构建的事件需要包含其当前的完整A n a : *上下文数据,以便后续系统有足够的信息可以进行业务逻辑处理与决策。这样可以避免后端系统在接收到事件后,需要进行当前事件对应上下文的组装,主要是解决由于传输存在的延迟导致相关数据可能已经不再是事件发生时的状态,存在状态不一致的情况

事件传输b = O ? z `

事件产: x L ) x y生后通常要发送到对应的消息代理服务进行暂存,在传统的业务中通! , * U Y t ,常会选择特定的消息协议来进行传输,这中间通常会涉# s P S {及两部分:序列化与传输协议。
基于云原生CloudEvent实现服务目录
在传输协议中Cloudevents中支持常见的行业标准协议比如HTTP、 AMQP7 ` & + . 7 #、 MQTT、 SMT等,并支持常见的供应商与平台( / o比如kafka、AWS Kinesis、 Azure 事件网格、Alibaba Cloud EventBridge,用户可以根据自己的场景选择对应的供应商分发对应的事件

在序列化方面cloudevents支持HTTP、 AMQP、t / # e t = Kafka等常见的标准协议,而不需要用户手动进行相关协议的序列化

事件消费A y m z J Q

事件的消费端通常会对其关注的事件类型感兴趣,并且由于消息的格式是统一的 / ) w Z e 3 0我们很容易就可以通过对应的平台来根据消息体里面的内容进行消息路由,分发给对应的事件消费者,事件的消费者只要负责对应事件的接收即可,而并不7 V = u关注其他的信息

关于Cloudevents事件2 f { l / j a , Q更多的内容,后面再继续分享,然后接下来就介绍下我们基于cloudevent是s 2 d + k C *怎么设计系统的

入门场景

在前面的文章中,介绍过我们的服务目录系! e U e _ S统,服务目录中要接入不同的基础服务,基础服务的格式各不相同,而且还要对接计费、效率统计等系统,后期可能还会对接公司的事件流平台,那如何对这些这些异构模块中异构的数据进行统一的分发和处理,我们的架构如下:

消息处理流程

基于云原生CloudEvent实现服务目录
首先在消息发送端,我们基于cloudevent构建对应的消息,并且将当% 9 = X W {前事件的上下文数据统一封装到data中,然后发送给公司的消息队列系统。由公司的消息队列来完成对z 3 ; m应的事件分发与路由,对应的事件接收端只需要定义自己关M n m 9 P c l s +注的事件,而不需要去监听具W k ` K )体的MQ,只需要定义一个接受消息的HTTP接口接口,对应消息的路由与分发功能由公司的MQ来实现
服务消费端解析消息队列传递过来的事P q X L { k O Z件信息,解析出对应的数据结构,然后进行业务处理即可。后续如果增加模块,或者增加新的事件消费需求,只需要实现对应J w x 7 h f % t的逻辑即可

数据结构

结合Cloudevents的规范,我们定义自己内部的系统的数据结构。主要使用的结构如下:

基于云原生CloudEvent实现服务目录

这里主要介绍下我们附加的一些字段以及根据自己场景的定义:

type
从表面上看Source和type都描述了当前事件发生的系统,不同的是type中是一个结构化的数据,按照这个结G : [ F E t构我们对应的U h ! & 1 V计费、效率统计模块,就可以拿到这个数据去做相关一些支线逻辑的处理了u ~ T c ,
resources: 变更资源列表
即标识当前事件触发了哪些D A 8相关资源的改变,比如虚机添加硬盘: S % 2,实际上是包含了两种资源即虚机与对应的磁盘资源

整合服务目录

前面提到我们使用服务和提供的API规范实现了一个服务代理模块,在服务代理模块中ClE ? v 4 l -oudevent@ f 1 & n A的主要使用场景如下:
基于云原生CloudEvent实现服务目录
1.服务目录接收到服务变更请求后,保存数据! 6 * Q = q库后,发生对应的cloudevent事件到消息队列
2.在消息队列中设定对应的路由转发规则,将对应的事件发生给服务代理模块
3.服务代理模块根据type字段进行: f L s解析,获取对应的后端服务地址,e Q H i & {并从消息中解析出对应的数据,将数据发送给后端真实的服务
4.后端真实服务接收到结构化数据后,进行自己的业务逻辑处理,处理完成后发送对应的事件
5.服务代理模块根据事件解析出相关的资源,调用对应的平台获取当I u L o x f I前资源的数据,生成事件
6.服务目录模块接收到对应的服务实例数据,存储到自己的数据库

如果后续有变更则只需要产生对应的事件发生到消息队列中,会重复进n Q O * v行5-6阶段

链路虽然有点长,但其实整个链路的系统设计非常简单,系统之间的通信、可靠性、容错、耦合性都不需要关注(消息队列服务来保障),后续如果要$ 9 8 F ) )扩展,就再怼个模块就可以了。要消费新的事+ Z g件,就再写个新的接口,然后编辑下路由规则,就可以实现新的模块的接入了。

后续

最近身体不好,今天刚去完医院,不能老熬夜。希望接下来能把项目进度赶上,后面+ M r i N就会有更多的场景了,年前要是进度赶上了,我就把想做的应用管理那个模块这块的代码实践抽空给写了,然后给大家分享下应用管理那块基于上E Q X y s述的实践,不过要是项目被砍了,就到这了吧。等最近上层的概念介绍完了, 就给大家分享一些源码上的设计,如果跟我做类似方向的朋友,也欢迎加微信交流交流。

原生学习笔记地址: https://www.yuT % fque.com/baxiaosh} C &i/tyado3
微信号:baxiaoshi2020 公共号: 图解源码3 , y % #
基于云原生CloudEvent实现服务目录