最近遇到一个很严肃的问题,什么样的 events 算是合格的 events 结构。为什么需要定义source,定义在设计 events 事件体时是否有可以直接遵守的规范。针对这个问题,我收集了大量资料,从基础接口设计规范到CloudEvents 调研。索性也薄浅的了解了一些,就分享下这块的心得吧。有接口设计方面诉求的同学可以参考下。不过大部分也是研发的字段定义诉求了。
首先,我们先来了解下什么是 Events。
Events(以下统称事件)在系统设计中其实已经变的无处不在,它主要是接口级的事件描述。理论来讲定义接口和接口产生的事件是一个比较简单的事儿,但是现在缺乏一种对事件的统一描述,服务使用方和提供方往往要花费大量的时间沟通字段定义,凭直觉设计事件属性,并在将来的使用过程中疲于新增或修改事件的属性。所以在云上,定义事件其实有个 CNCF(云原生计算基金会) 牵头的 CloudEvents 标准协议来制定所有的服务事件规范。这其实也算是业内比较惯常使用的了(当然不包括 AWS,google 原因大家都懂, Azure 支持很到位)。
好了,这个应该很好理解,大体就是服务通过怎样的格式投递使用。
概念篇
那么从事件源到触发,整个流程是怎样的呢?下图很好的解释了里面的关系:
云服务代码中通常使用事件来连接不同的系统,其中一个系统中状态的改变会导致代码在另一个系统中执行。例如,当 Source 源接收到外部信号(例如HTTP或RPC)或检测到系统变化的值,它便会生成事件。Source 生成一条消息并将其中事件封装在协议中,事件到达目的地,触发事件数据并调用。
事件本身其实可以通过各种行业标准协议(例如HTTP,AMQP,MQTT,SMTP),开放源代码协议(例如Kafka,NATS)来传递,当然云厂商产生的事件其实一般是由厂商自定义的,这类事件也是本次探讨的核心。
action 的定义其实往往是指事件所附带的特定的事件触发。通常情况下,源是某种托管服务,而操作通常是 Serverless(无服务器化)的能力(例如AWS Lambda 或云函数 SCF)中的自定义代码。
定义篇
大体的概念大致梳理清楚了,那下面我们来看看最重要的定义,搞清楚定义,我们才能更好的研究事件的范围是如何的。
首先,我们来看下必选参数的定义:
id
类型: String
描述:事件标识,生产者必须确保source+id 对于每个不同的事件都是唯一的。如果重复事件被重新发送(例如网络错误),允许具有相同的id。消费者可以假设事件具有相同source且id重复。
source
类型: URI-reference描述:标识事件发生的上下文,通常将包括诸如事件源的类型,发布事件的组件或产生事件的过程之类的信息。一般由事件生产者定义数据背后的确切语法和语义。生产者必须确保source+id对于每个不同的事件都是唯一的。应用程序可以使用UUID,URN,DNS 授权或特定于整体技术架构的方案来创建唯一 source 标识符。
一个来源可以包括多个生产者。
type
类型: String
说明:该参数包含一个描述与源事件相关的事件类型。通常用于路由,策略执行等。格式应该由生产者定义,并且可能包含诸如的版本之类的信息。
其次,是非必选参数定义:
datacontenttype
类型:String描述:data 值的内容类型,该参数允许 data 赋予任何类型的内容。例如,通常使用 JSON 格式事件可能也会通过XML返回data信息,此时可以通过将此属性设置为“ application/xml”来通知使用者。
time
类型: Timestamp
描述:发生该事件的时间戳,如果不能确定发生时间,则生产者可以将此属性设置为其他时间(例如当前时间),但是所有生产者source必须保持一致。换句话说就是要么全部使用实际事件发生时间,要么全部使用相同的时间获取方式来确定所使用的时间戳。
核心参数的定义大抵如此了,其次是一些 Event Data,Attributes,和相关扩展字段,这里就不一一阐述了。这里给放个例子,也是 cloudevents 官方用例,可以供大家参考:
{ "specversion" : "1.0", // cloudevent版本信息 选择性填写即可 "type" : "com.github.pull.create", "source" : "https://github.com/cloudevents/spec/pull", "subject" : "123", "id" : "A234-1234-1234", "time" : "2020-04-05T17:31:00Z", "comexampleextension1" : "value", "comexampleothervalue" : 5, "datacontenttype" : "text/xml", "data" : "<much wow=\"xml\"/>" }
总结篇
CloudEvents 的核心其实是定义了一组关于不同组件间传输事件的元数据,以及这些元数据应该如何出现在消息体中。
其主旨大抵如下:
- 事件规范化
- 降低平台集成难度
- 提高FaaS的可移植性
- 源事件可追踪
- 提升事件关联性
准确的事件体,事件信息才可以做出更稳定的系统架构,永远保持对事件的敬畏。
附 一些术语及定义:
Occurrence:发生,指事件逻辑上的发生,基于某种情况,事件出现了。
Event:事件,表示事件以及上下文的数据记录。可以根据事件中的信息决定路由,但事件本身并不包含路由信息。
Producer:生产者,真正创造事件的实例或组件
Source:源,事件发生的上下文,可以由多个producer组成。
Consumer:消费者,接收事件并对事件进行消费
Intermediary:中介,接收包含事件的消息(message),并转发给下一个接收方,类似路由器
Context:上下文,上下文元数据被封装到context attributes中。用来判断事件与其它系统的关系
Data:数据,也可以叫做 payload
EventFormat:事件格式,例如 json
Message:消息,封装事件并将其从source传递到destination。
Protocol:协议,可以是行业标准如 http,开源协议如 kafka 或者供应商协议如 AWS Kinesis
Protocol Binding:协议绑定,描述如何通过给定的协议收发事件,如何将事件放到消息里
I got good info from your blog
Everything is very open and very clear explanation of issues. was truly information. Your website is very useful. Thanks for sharing.
Some really nice and utilitarian information on this web site, likewise I believe the design has great features.
I like this post, enjoyed this one regards for posting.
I just couldn’t depart your web site prior to suggesting that I extremely enjoyed the standard info a person provide for your visitors? Is going to be back often in order to check up on new posts