CloudEvents规范
- 1: CloudEvents概述
- 2: CloudEvents规范
- 3: CloudEvents入门
- 4: 核心规范
- 5: HTTP Protocol Binding
- 6: Json事件格式
- 7: SDK需求
1 - CloudEvents概述
介绍
CloudEvents是一种以通用方式描述事件数据的规范。CloudEvents旨在简化跨服务,平台及其他方面的事件声明和发送。CloudEvents 最初由 CNCF Severless 工作组提出。
A specification for describing event data in a common way
以通用方式描述事件数据的规范
为什么需要CloudEvents?
事件无处不在,然而事件发布者对事件的描述却往往不尽相同。
- 一致性:缺乏通用的事件描述方式,意味着开发人员必须为每个事件源编写新的事件处理逻辑。
- 无障碍环境:没有通用的事件格式意味着没有通用的库、工具和基础设施来跨环境投递事件数据。CloudEvents提供了Go、JavaScript、Java、C#、Ruby和Python的SDK,可用于构建事件路由器、跟踪系统和其他工具。
- 可移植性:整体上阻碍了我们从事件数据中实现的可移植性和生产力。
什么是CloudEvents?
CloudEvents 是一个以通用方式描述事件数据的规范。CloudEvents旨在大幅简化跨服务、跨平台的事件声明和投递。
CloudEvents是一项新的工作,目前仍在积极开发中。然而,它的工作小组已经收到了令人惊讶的行业兴趣,从主要的云提供商到流行的SaaS公司都有。该规范现在由云原生计算基金会(Cloud Native Computing Foundation/CNCF)负责。
CloudEvents是通过CNCF的Serverless工作组组织的。
1.0版本
2019年10月24日,CloudEvents项目取得了两项重大成果。第一,CNCF的技术监督委员会批准该项目成为 “孵化器 “项目(从而使其从CNCF的 “沙盒"毕业)。第二,CloudEvents规范发布了1.0版本!
这是该规范的第一个主要版本,代表了整个serverless社区中一个真正伟大的团队两年来的努力工作。我们已经有几乎所有主要的云提供商参与其中,还有一些 “终端用户 “公司以及许多个人参与者,他们都在努力工作以制作出一个规范,希望在这一里程碑式的发展过程中,能够继续得到更多的采用。
除了核心的CloudEvents规范外,还有Primer和协议及格式规范,所有这些都可以在GitHub repo中找到。此外,还有六种不同的SDK-Go、JavaScript、Java、C#、Ruby和Python,帮助生产和消费CloudEvents。
CNCF Serverless工作组将决定下一步的工作重点(例如,额外的CloudEvents相关活动,或者解决社区正在经历的其他互操作性痛点)。所以,如果你有兴趣,请加入每周的定期电话会议。此外,还有工作流规范方面的工作正在进行中。
历史
CNCF Severless 工作组最初是由 CNCF 技术监督委员会创立的,旨在调查 Serverless 技术和指导 CNCF 在本领域下一步可能展开的相关工作的建议。其中一项建议是创建一个通用的 Event Format,以在不同云供应商提供的Function 之间实现可移植性和事件流处理的互操作性。CloudEvents 规范因此被创建出来。
尽管 CloudEvents 的工作最初是作为 Serverless 工作组的一部分开展的,当规范到达 v0.1 里程碑之后,TOC 批准了 CloudEvents 成为一个独立的 CNCF 沙盒项目。
TODO:补充发展过程。
集成
支持情况 | ||
---|---|---|
Azure Event Grid | Event Grid原生支持CloudEvents v1.0 JSON实现中的事件和HTTP协议绑定。 | |
Knative Eventing | 所有由Knative Eventing service产生和消费的事件数据均符合CloudEvents标准 | |
Serverless.com Event Gateway | 函数从事件网关接收的所有事件数据均符合 CloudEvents 标准 | |
OpenFaaS | CloudEvent事件是OpenFaaS函数的众多可用触发器之一。 | |
Choria | Choria 编排系统发出的所有生命周期和自主代理事件都符合 CloudEvents 的标准。 | |
Oracle Cloud | Oracle云基础设施事件服务实现了CloudEvents |
2 - CloudEvents规范
介绍
备注:以下内容来自 https://github.com/cloudevents/spec
事件无处不在。然而,事件生产者倾向于以不同的方式来描述事件。
缺乏通用的描述事件的方式意味着开发人员必须不断地重新学习如何消费事件。这也限制了类库、工具和基础设施在跨环境时发送事件数据的潜力,如SDK、事件路由器或跟踪系统等。我们从事件数据中实现的可移植性和生产力总体上受到了阻碍。
CloudEvents是一个用通用格式描述事件数据的规范,以提供跨服务、跨平台和跨系统的互操作性。
CloudEvents得到了大量的行业关注,从主要的云提供商到流行的SaaS公司都有。CloudEvents由云原生计算基金会(CNCF)主办,于2018年5月15日获批为云原生沙盒级项目。
CloudEvents文档
包括核心规范,可选规范和额外文档三部分。
如果是 CloudEvents 的新手,建议先阅读 Primer,了解规范的目标和设计决策,然后继续阅读核心规范。
由于并非所有事件生产者都会默认生成 CloudEvents,因此有文档描述了将一些常用事件适配到 CloudEvents 的推荐过程,请参阅 CloudEvents Adapters。
流程
CloudEvents项目致力于根据设计目标正式确定规范,设计目标侧重于生成和响应事件的系统之间的互操作性。
为了实现这些目标,项目必须描述:
- 促进互操作性的事件的公共属性
- 一个或多个现在正在使用或计划由其成员构建的通用体系结构
- 如何将事件从生产者传输到消费者,通过至少一种协议
- 识别并解决互操作性所需的任何其他内容
3 - CloudEvents入门
备注:以下内容来自 https://github.com/cloudevents/spec/blob/v1.0/primer.md
概要
本文不是规范性文档,但本文概述了CloudEvents规范。本文旨在对CloudEvent规范进行补充,以提供对规范制定过程中制定的历史和设计决策的更多背景知识和见解。这使规范本身可以专注于规范性的技术细节。
历史
CNCF无服务器工作组最初是由CNCF技术监督委员会设立的,目的是调查无服务器技术,并为CNCF在这一领域的一些相关活动提出一些可能的下一步建议。其中一项建议是调查创建一种通用的事件格式,以帮助云提供商之间的函数可移植性和事件流处理的互操作性。因此,CloudEvents 规范应运而生。
虽然最初CloudEvents的工作是作为无服务器工作组的一部分完成的,但在规范达到v0.1的里程碑之后,TOC批准了CloudEvents工作,将其作为一个新的独立的CNCF沙盒项目。
CloudEvents的概念
事件(Event)包含和发生(Occurrence)相关的上下文和数据。每一个发生(Occurrence)都由事件的数据唯一标识。
事件代表事实,因此不包括目的地,而消息则传达意图,将数据从源头传送到特定的目的地。
Events represent facts and therefore do not include a destination, whereas messages convey intent, transporting data from a source to a given destination.
Eventing
在服务器端代码中,事件通常用于连接不同的系统,其中一个系统的状态变化会导致另一个系统的代码执行。例如,当源接收到外部信号(如 HTTP 或 RPC)或观察到一个变化的值(如 IoT 传感器或非活动期)时,可能会产生一个事件。
为了说明系统如何使用 CloudEvents,下面的简化图显示了来自源的事件如何触发一个动作。
源(Source)生成消息(Message),其中事件(Event)被封装在协议中。事件到达目的地,触发一个由事件数据提供的动作(Action)。
源是源类型的一个特定实例,它允许staging和测试实例。一个特定源类型的开放源软件可以由多个公司或供应商部署。
事件可以通过各种行业标准协议(如HTTP、AMQP、MQTT、SMTP)、开源协议(如Kafka、NATS)或平台/供应商特定的协议(AWS Kinesis、Azure Event Grid)来递送。
动作处理定义了由特定源的特定事件触发的行为或效果的事件。虽然不在本规范的范围内,但生成事件的目的通常是为了让其他系统能够轻松地对它们无法控制的源中的变化做出反应。源和动作通常是由不同的开发人员建立的。通常情况下,源是一个托管服务,而动作是无服务器函数(如AWS Lambda或Google Cloud Functions)中的自定义代码。
设计目标
CloudEvents通常用于分布式系统中,允许服务在开发过程中松散耦合,独立部署,稍后可以连接起来创建新的应用。
CloudEvents规范的目标是定义事件系统的互操作性,允许服务产生或消费事件,其中生产者和消费者可以独立开发和部署。生产者可以在消费者监听之前产生事件,而消费者可以对尚未产生的事件或事件类表达兴趣。请注意,这项工作所产生的规范侧重于事件格式的互操作性,以及事件在HTTP等各种协议上发送时如何呈现。该规范将不关注事件生产者或事件消费者的处理模型。
CloudEvents 的核心是定义了一组关于系统间传输事件的元数据(被称为属性),以及这些元数据应该如何出现在该消息中。这些元数据是将请求路由到适当的组件并促进该组件对事件进行适当处理所需的最低限度的信息集。因此,虽然这可能意味着事件本身的一些应用数据可能会和作为 CloudEvent 属性集的一部分重复,但这只是为了正确传递和处理消息的目的。不用于此目的的数据应放在事件(数据)本身中。
此外,假定协议层向目标系统传递消息所需的元数据完全由协议处理,因此不包含在 CloudEvents 属性中。有关详细信息,请参阅 “非目标 “部分。
在定义这些属性的同时,还将对如何以不同格式(如 JSON)和协议(如 HTTP、AMQP、Kafka)序列化事件进行规范。
一些协议原生支持将多个事件批量化为一个API调用。为了帮助实现互操作性,是否需要批处理和如何实现批处理由协议决定。详情可在协议绑定或协议规范中找到。CloudEvents 的批处理没有语义意义,也没有顺序。中间人可以添加或删除批处理,也可以将事件分配给不同的批次。
非目标
以下内容被认为超出了本规范的范围。
- 函数的建立和调用过程
- 特定语言的运行时API
- 选择单一身份/访问控制系统
- 包含协议级的路由信息
- 事件持久化过程
CloudEvents 规范将不包括协议级的路由信息(例如,发送事件的目标 URL)。这是对CloudEvents概念的新手提出的一个常见建议。经过多次讨论后,工作组得出结论:规范中没有必要包含路由信息:任何协议(如 HTTP、MQTT、XMPP 或 Pub/Sub 总线)都已经定义了路由的语义。例如,CloudEvents HTTP 绑定规定了头和请求正文内容。CloudEvents 不需要在规范中包含目标 URL 才能兼容 HTTP;HTTP 规范已经在 Request-Line 中包含了一个目标 URL。
路由信息不仅是多余的,而且会分散注意力。CloudEvents 应该增加互操作性,并将事件的生产者和消费者解耦。禁止事件格式中的路由信息,可以让CloudEvents重新传递给新的Action,或者通过包含多个通道的复杂中继器传递。例如,如果 Webhook 地址不可用,则原定用于 Webhook 的 CloudEvent 应可投递给死信队列。该死信队列应该能够将事件送入原始事件发出者从未想过的新的Action。
在系统内和跨系统产生和消费的CloudEvents会触发行为,从而产生价值。因此,归档和/或重放事件对于调试或复制来说是非常有价值的。然而,持久化事件会删除传输过程中可用的上下文信息,如生产者的身份和权利、保真验证机制或保密保护。此外,持久化会增加复杂性和挑战,以满足用户的需求。例如,重复使用私钥进行加密或签名,会增加攻击者可用的信息,从而降低安全性。预计可能会定义出有助于满足持久性要求的属性,但预计这些属性将随着行业最佳实践和进步而不断发展。
架构
CloudEvents 规范集定义了四种不同类型的协议元素,它们构成了一个分层架构模型。
-
基本规范 定义了由属性(键值对)和相关规则组成的抽象信息模型,这些属性和相关规则构成了CloudEvents。
-
扩展 添加了特定的、可能重叠的扩展属性和相关规则集,例如,支持不同的跟踪标准。
-
事件格式编码(如 JSON)定义了基本规范的信息模型和所选扩展的编码方式,以将其映射到应用协议的头和有效载荷元素。
-
协议绑定,例如 HTTP,定义了 CloudEvent 如何与应用协议的传输帧绑定,在 HTTP 的下是绑定 HTTP 消息。协议绑定并不约束传输帧的使用方式,这意味着HTTP绑定可以与任何HTTP方法以及请求和响应消息一起使用。
如果需要确保更广泛的互操作性,CloudEvents 规范集为使用特定应用协议的事件传递提供了特定的约束。HTTP Webhook 规范并不是 CloudEvents 所特有的,它可以用于将任何类型的单向事件和通知发布到符合的 HTTP 端点。然而,由于其他地方缺乏这样的规范,因此CloudEvents有必要定义它。
协议错误处理
大多数情况下,CloudEvents 规范并没有规定与创建或处理 CloudEvents 相关的处理模型。因此,如果在处理 CloudEvents 过程中出现错误,鼓励遇到错误的软件使用常规的协议级错误报告来报告错误。
属性的版本化
对于某些 CloudEvents 属性,其值所引用的实体或数据模型可能会随着时间的推移而变化。例如,dataschema 可能会引用模式文档的一个特定版本。通常情况下,这些属性值将通过在其值中包含某些特定于版本的字符串作为其值的一部分来区分每个变体。例如,可能会使用版本号(v1、v2)或日期(2018-01-01-01)。
CloudEvents 规范并没有规定要使用任何特定的模式,甚至根本不要求使用版本字符串。此决定权在每个事件制生产者手中。但是,当包含特定版本字符串时,应注意其值的变化,因为事件的消费者可能会依赖现有的值,因此变化可能会被解释为 “破坏性变化”。应该在生产者和消费者之间建立某种形式的沟通,以确保事件消费者知道可能使用的值。一般来说,所有 CloudEvents 属性也是如此。
CloudEvent属性
本节提供了与CloudEvent的一些属性相关的其他背景和设计要点。
id
id 属性是指在与一个事件源相关的所有事件中都是唯一的值(每个事件源都是由其 CloudEvents 的 source 属性值唯一标识的)。虽然所使用的确切值由生产者定义,但可以保证来自单一事件源的 CloudEvents 接收者不会有两个事件共享相同的 id 值。唯一的例外情况是,如果支持事件的某些重播,在这种情况下,可以使用 id 来检测。
由于一个事件的发生可能会产生一个以上的事件,所以在所有这些事件都来自同一个事件源的情况下,每个 CloudEvent 构造的事件都有一个唯一的 id。以创建 DB 条目为例,这一次发生可能会产生一个创建类型为 create 的 CloudEvent 和一个写类型为 write 的 CloudEvent。这些CloudEvents中的每一个都有一个唯一的id。如果希望这两个 CloudEvents 之间有一定的相关性,以表明它们都与同一事件相关,那么 CloudEvent 中的一些附加数据将用于此目的。
在这方面,虽然事件生成者选择的确切值可能是一些随机字符串,或在其他语境中具有某种语义意义的字符串,但对于本CloudEvent属性的目的来说,这些意义并不相关,因此,将id用于唯一性检查之外的其他目的不在本规范的范围内,也不建议使用。
CloudEvent 属性扩展
为了实现既定目标,规范作者将试图限制他们在 CloudEvents 中定义的元数据属性的数量。为此,本项目所定义的属性将分为三类。
- required / 必须的
- optional / 可选的
- extensions / 扩展
正如类别名称所暗示的那样,“必需 “属性将是该组认为在所有用例中对所有事件至关重要的属性,而 “可选 “属性将在大多数情况下使用。这两种情况下的属性都将在规范本身中定义。
当小组确定一个属性不够通用,不能归入这两类,但仍然可以从定义良好的互操作性中受益,那么它们将被归入 “扩展 “类别,并被归入文档化的扩展。该规范定义了这些扩展属性在 CloudEvent 中的出现方式。
在确定提议的属性属于哪个类别时,甚至在确定是否将其包含在其中时,小组会使用用例和用户故事来解释其理由和需求。这些支持信息将被添加到本文档的 “Prior Art “部分。
CloudEvent 规范的扩展属性是指需要包含的额外元数据,以帮助确保 CloudEvent 的正确路由和处理。与事件本身相关且在传输或处理 CloudEvent 中不需要的其他目的的附加元数据,应放在事件(数据)本身的适当扩展点中。
扩展属性应保持最小化,以确保 CloudEvent 能够正确地序列化和传输。例如,事件制作者应考虑向 CloudEvent 添加扩展时可能会遇到的技术限制。例如,HTTP二进制模式使用HTTP头来传输元数据;大多数HTTP服务器会拒绝HTTP header数据过多的请求,限制低至8kb。因此,应该尽量减少扩展属性的总大小和数量。
如果一个扩展变得流行,那么规范作者可能会考虑将其作为核心属性移到规范中。这意味着在正式加入规范之前,扩展机制/进程可以作为一种方式来审核新属性,然后再正式加入到规范中。
JSON扩展
正如在CloudEvents规范的JSON事件格式中的Attributes部分提到的那样,CloudEvent扩展属性被序列化为规范定义的属性的兄弟姐妹–也就是说,在JSON对象的顶层。该规范的作者花了很长时间考虑了所有选项,并决定这是最好的选择。以下是其中的一些道理。
由于规范遵循 semver(语义化版本),这意味着新的属性可以被未来版本的核心规范所定义,而不需要重大的版本号改变–只要这些属性是可选的。在这种情况下,考虑一下现有的消费者会如何处理一个新的(未知)顶层属性。虽然它可以自由地忽略它,因为它是可选的,但在大多数情况下,相信这些属性仍然希望暴露在接收这些事件的应用程序中。这将允许这些应用程序支持这些属性,即使基础设施不支持这些属性。这意味着,未知的顶层属性(不管是谁定义的–不管是未来版本的规范还是事件生产者)很可能不会被忽略。因此,虽然其他一些规范定义了一个特定的属性来放置扩展属性(例如顶层扩展属性),但作者决定,在一个传入的事件中,为未知的属性设置两个不同的位置,可能会导致互操作性问题,也会给开发者带来混乱。
通常情况下,在规范正式采用之前,扩展通常是用来测试规范的新的潜在属性。如果有一个扩展类型的属性,在这个新属性中,这个新属性被序列化了,那么,如果这个属性曾经被核心规范采用,那么它将从扩展属性中晋升(从序列化的角度来看)为顶层属性。如果我们假设这个新属性将是可选的,那么随着它被核心规范采用,它将只是一个小的版本增量,所有现有的消费者仍然应该继续工作。然而,消费者将不知道这个属性将出现在哪里–在扩展属性中或作为顶层属性。这意味着他们可能需要在这两个地方都要找。如果这个属性同时出现在两个地方,但价值不同怎么办?生产者是否需要将其放在两个地方,因为他们可能会有新老消费者?虽然可能有可能定义明确的规则来解决每一个可能出现的问题,但作者决定最好是一开始就简单地避免所有问题,在序列化中只为未知的、甚至是新的属性提供一个位置。此外,还有人指出,现在的HTTP规范也遵循了类似的模式,不再建议在HTTP扩展头中用X-作为前缀。
创建CloudEvents
CloudEvents 规范特意避免过强的规定如何创建 CloudEvents。例如,它不假定原始事件源是为该事件的发生构造相关的 CloudEvents 的同一个实体。这样就可以有多种实现选择。但是,对于规范的实现者来说,了解规范作者的期望值是很有用的,因为这可能有助于确保互操作性和一致性。
如上所述,生成初始事件的实体是否是创建相应的 CloudEvent 的实体是一个实现选择。然而,当构造/填充 CloudEvents 属性的实体代表事件源行事时,这些属性的值是为了描述事件或事件源,而不是计算 CloudEvent 属性值的实体。换句话说,当事件源和 CloudEvents 生产者之间的分工对事件消费者没有实质性的意义时,规范定义的属性通常不会包含任何值来表示这种责任的分工。
这并不是说 CloudEvents 生产者不能为 CloudEvents 添加一些额外的属性,但这些属性不属于规范中互操作性定义的属性范围。这就类似于 HTTP 代理通常会尽量减少对传入消息中定义好的 HTTP 标头的更改,但它可能会添加一些包含代理特定元数据的附加标头。
还值得注意的是,原始事件源和 CloudEvents 生产者之间的这种分离可以是小的或大的。这意味着,即使CloudEvents 生产者不属于原始事件源的生态系统的一部分,但如果它是代表事件源行事,并且它在事件流中的存在对事件消费者来说没有意义,那么上述指导仍然适用。
当一个实体同时充当CloudEvents的接收方和发送方,以转发或转换入站事件为目的时,出站CloudEvent与入站CloudEvent的匹配程度将根据该实体的处理语义而有所不同。如果它作为代理,只是将 CloudEvents 转发到另一个事件消费者,那么出站 CloudEvent 通常与入站 CloudEvent 在规范定义的属性方面看起来与入站 CloudEvent 完全相同 - 请参见上一段关于添加附加属性的内容。
但是,如果这个实体正在对CloudEvent进行某种类型的语义处理,通常会导致数据属性的值发生变化,那么它可能需要被视为一个与原始事件源不同的 “事件源”。因此,预计与事件生产者相关的CloudEvents属性(如源和id)将从传入的CloudEvent中更改。
合格的协议和编码
正如规范中所表达的那样,CloudEvents工作的明确目标是 “以通用的方式描述事件数据”,并 “定义事件系统的互操作性,使服务能够产生或消费事件,生产者和消费者可以独立开发和部署”。
这种互操作性的基础是开放的数据格式和开放的协议,CloudEvents旨在提供这种开放的数据格式,并将其数据格式投射到常用的协议和常用的编码上。
尽管每个软件或服务产品和项目显然可以选择自己喜欢的通信形式,但毫无疑问,对这种产品或项目私有的专有协议并不能促进事件生产者和消费者之间的广泛互操作性的目标。
特别是在消息传递和事件处理领域,过去十年来,业界在开发一个强大的、广泛支持的协议基础上取得了重大进展,比如HTTP 1.1和HTTP/2以及WebSockets或事件网络上的WebSockets或事件,或者是面向连接的消息传递和遥测传输的MQTT和AMQP。
一些被广泛使用的协议已经成为事实上的标准,有些协议是由三家或更多公司组成的顶级联盟组成的强大的生态系统中产生的,有些则是由一家公司发布的强大的项目生态系统中产生的,无论在哪种情况下,都是与前面提到的标准栈的演进同步进行的。
CloudEvents 的努力不应成为一种载体,甚至不应成为暗中认可或推广项目或产品专有协议的工具,因为这将会对 CloudEvents 的最初目标产生反作用。
要使协议或编码符合 CloudEvents 核心事件格式或协议绑定的资格,它必须属于以下任一类别。
- 该协议具有作为标准的正式地位,具有广泛认可的多厂商协议标准化机构(如 W3C、IETF、OASIS、ISO)的标准地位
- 该协议在其生态系统类别中具有 “非事实标准 “的地位,这意味着它被广泛使用,以至于被认为是特定应用的标准。实际上,我们希望看到至少有一家厂商中立的开源组织(如Apache、Eclipse、CNCF、.NET基金会)旗下至少有一个开源实现,并且至少有十几家独立的厂商在其产品/服务中使用该协议。
除了正式地位之外,协议或编码是否符合核心 CloudEvents 事件格式或协议绑定的关键标准是,该组是否同意该规范将为与协议或编码产生的产品或项目无关的任何一方带来持续的实际利益。这方面的一个基本要求是,协议或编码的定义方式必须允许独立于产品或项目的代码之外的替代实现。
欢迎将 CloudEvents 的所有其他协议和编码格式纳入指向各自项目自己的公共存储库或网站中的 CloudEvents 绑定信息的列表中。
专有协议和编码
为鼓励采用 CloudEvents,本存储库将收集 CloudEvents 专有协议和编码的专有协议和编码的 CloudEvents 规范,不作任何认可。存储库维护者不负责创建、维护或通知专有规范的维护者与 CloudEvents 规范的偏离。
专有规范将托管在自己的存储库或文档站点中,并在专有规范文件中收集。专有规范应遵循与核心协议和编码的其他规范相同的格式。
专有规范比核心规范的审查要少,随着 CloudEvents 规范的发展,各协议和编码的维护者有责任使规范与 CloudEvents 规范保持同步。如果专有规范过时过久,CloudEvents 可能会将该规范的链接标记为过时或删除。
如果为同一协议创建了多个不兼容的规范,存储库维护者将不知道哪个规范是正确的,并列出所有规范的链接。
Prior Art
TODO:以后再细看。
价值主张
本节介绍了一些解释CloudEvents价值的用例。
-
跨服务和平台的事件规范化
主要的事件发布商(如AWS、微软、谷歌等)都在各自的平台上以不同的格式发布事件。甚至有少数情况下,同一提供商上的服务以不同的格式发布事件(如AWS)。这就迫使事件消费者不得不实施自定义逻辑,以实现跨平台、偶尔跨服务在单一平台上读取或合并事件数据。
CloudEvents 可以为处理跨平台和跨服务的事件的消费者提供单一体验。
-
促进跨服务和平台的集成
事件数据跨环境传输的情况越来越普遍。然而,如果没有一种通用的描述事件的方式,事件的跨环境传输就会受到阻碍。没有单一的方法来确定事件的来源和可能的去向。这就阻碍了促进事件成功交付的工具化,也阻碍了消费者知道如何处理事件数据。
CloudEvents 提供了有用的元数据,中间件和消费者可以依赖这些元数据来促进事件的路由、记录、传递和接收。
-
提高FaaS的可移植性
FaaS(也称无服务器计算)是IT领域发展最快的趋势之一,它主要是由事件驱动的。然而,FaaS的一个主要问题是供应商的锁定问题。这种锁定部分是由各供应商之间的函数API和签名的差异造成的,但这种锁定也是由函数内部接收事件数据的格式差异造成的。
CloudEvents 对事件数据的通用描述方式提高了FaaS的可移植性。
-
改进事件驱动/无服务器架构的开发和测试工作
由于缺乏通用的事件格式,使得事件驱动和无服务器架构的开发和测试变得复杂化。没有简单的方法可以准确地模拟事件用于开发和测试,并帮助在开发环境中模拟事件驱动的工作流程。
CloudEvents可以使开发人员有更好的工具来构建、测试和处理事件驱动和无服务器架构的端到端生命周期。
-
事件数据演变
大多数平台和服务对其事件的数据模型进行了不同的版本(如果他们根本不这么做的话)。这为发布和消费事件的数据模型创造了不一致的体验,因为这些数据模型在不断发展。
CloudEvents 可以提供一种通用的方式来版本化和演进事件数据。这将帮助事件发布者根据最佳实践安全地对其数据模型进行版本化,这将帮助事件消费者在事件数据演进过程中安全地使用事件数据。
-
规范化Webhooks
Webhooks是一种没有使用通用格式的事件发布方式。Webhooks 的消费者没有一致的方式来开发、测试、识别、验证和整体处理通过 Webhooks 传递的事件数据。
CloudEvents 可以为 webhook 发布和消费提供一致性。
-
政策执行
处于安全和策略的考虑,系统之间的事件的传送可能需要过滤、转换或阻止。例如,为了防止事件的进入或流出,如事件数据包含敏感信息或希望禁止发送方和接收方之间的信息流。
一个通用的事件格式将使人们更容易推理正在流转的数据,并允许对数据进行更好的反省。
-
事件追踪
从源发送的事件可能会导致从各种中间件设备(如事件代理和网关)发送的附加事件序列。CloudEvents 包含事件中的元数据,可将这些事件作为事件序列的一部分进行关联,以进行事件追踪和故障排除。
-
IoT / 物联网
物联网设备会发送和接收与其函数相关的事件。例如,一个连接的恒温器将发送关于当前温度的遥测数据,并可以接收改变温度的事件。这些设备通常有一个受限制的操作环境(CPU、内存),需要一个定义良好的事件消息格式。在很多情况下,这些消息是二进制编码的,而不是文本的。无论是直接来自设备还是通过网关转换,CloudEvents 都可以更好地描述消息的来源和消息中包含的数据格式。
-
事件的关联性
一个无服务器的应用程序/工作流可以与来自不同事件源/生产者的多个事件相关联。例如,一个防盗侦测应用/工作流可能同时涉及一个运动事件和一个门窗打开事件。一个无服务器平台可以接收到许多不同类型事件的实例,例如,它可以接收来自不同房屋的运动事件和门窗打开事件。
无服务器平台需要将一种类型的事件实例与其他类型的事件实例正确关联,并将接收到的事件实例映射到正确的应用/工作流实例。CloudEvents 将为任何事件消费者(如无服务器平台)提供一种标准的方法,以便在事件数据中找到事件关联信息/标记,并将接收到的事件实例映射到正确的应用/工作流实例。
现有的事件格式
与上一节一样,对世界现状的审查(和了解)对小组来说非常重要。为此,我们收集了目前实践中使用的现有事件格式的样本。
具体格式内容见原文
4 - 核心规范
备注:内容来自 https://github.com/cloudevents/spec/blob/v1.0/spec.md
摘要
CloudEvents 是一个厂商中立的规范,用于定义事件数据的格式。
概述
事件无处不在。然而,事件生产者往往会以不同的方式来描述事件。
缺乏描述事件的常用方法意味着开发人员必须不断重新学习如何接收事件。这也限制了库,工具和基础设施的可能性,以帮助跨环境(如SDK,事件路由器或跟踪系统)发送事件数据。我们可以从事件数据中实现的可移植性和生产力总体上受到阻碍。
CloudEvents 是一种用通用格式描述事件数据的规范,以提供跨服务、平台和系统的互操作性。
事件格式指定了如何用特定的编码格式对 CloudEvents 进行序列化。支持这些编码的 CloudEvents 实现必须遵守相应事件格式中指定的编码规则。所有实现都必须支持 JSON 格式。
设计目标
这一段应该是搬到prier里面去了
CloudEvents通常用于分布式系统,以允许服务在开发期间松散耦合,独立部署,以后可以连接以创建新应用程序。
CloudEvents规范的目标是定义事件系统的互操作性,这些事件系统允许服务生成或消费事件,其中生产者和消费者可以独立开发和部署。生产者可以在消费者收听之前生成事件,并且消费者可以表达对尚未生成的事件或事件类别的兴趣。
为此,规范将包括促进互操作性的事件的公共元数据属性,而事件不包含可能用于发送事件的消费者或传输的任何细节。
非目标
以下内容不在规范中:
- 函数构建和调用过程
- 特定于语言的运行时API
- 选择单一身份/访问控制系统
使用场景
下面的列表列举了为开发此规范而考虑的关键使用场景和开发人员视角。这些使用场景并非详尽无遗,并且该规范并非旨在规定如何使用。
这些情景不是规范性的; 任何人都可以自由地创建一个混合这些场景的系统。 这些案例建立了事件生成器,消费者,中间件和框架的通用词汇表。
在这些场景中,我们将事件生成器和事件使用者的角色保持不同。 单个应用程序上下文始终可以同时承担多个角色,包括既是事件生产者又是事件消费者。
-
应用程序生成供其他方使用的事件,例如为消费者提供有关终端用户活动,状态更改或环境观察的见解,或允许通过事件驱动的扩展来补充应用程序的功能。
通常生成与上下文或生产者选择的分类相关的事件。例如,房间中的温度传感器可能由安装位置,房间,楼层和建筑物进行上下文限定。运动会结果可能按联赛和球队分类。
生产者应用程序可以在任何地方运行,例如在服务器或设备上运行。
生产的事件可以由生产者或中间人直接呈现和发布; 作为后者的示例,考虑由设备在诸如LoRaWAN或ModBus之类的有效载荷大小约束的网络上发送的事件数据,并且其中符合该规范的事件将由网络网关代表生产者呈现。
例如,气象站通过LoRaWAN每5分钟发送一个12字节的专有事件有效载荷,指示天气状况。 然后使用LoRaWAN网关以CloudEvents格式将事件发布到Internet目标。LoRaWAN网关是事件生产者,代表气象站发布,并将适当地设置事件元数据以反映事件的来源。
-
应用程序将事件用于显示,归档,分析,工作流程处理,监视条件和/或为业务解决方案及其基础构建块的操作提供透明度等目的。
消费者应用程序可以在任何地方运行,例如在服务器或设备上运行。
消费事件的应用程序通常会对以下内容感兴趣:
- 区分事件,使得完全相同的事件不会被处理两次。
- 识别和选择原始上下文或生产者指定的分类。
- 识别事件相对于始发上下文和/或相对于挂钟的时间顺序。
- 理解事件中携带的与上下文相关的详细信息。
- 关联来自多个事件生成器的事件实例,并将它们发送到相同的使用者上下文。
在某些情况下,消费应用程序可能对以下内容感兴趣:
- 从原始上下文获取有关事件主题的更多详细信息,例如获取有关需要特别访问授权的已更改对象的详细信息。例如,HR解决方案可能出于隐私原因在事件中仅发布非常有限的信息,并且任何需要更多数据的事件消费者将必须用他们自己的授权上下文中从HR系统获得与事件相关的细节。
- 在原始上下文中与事件的主题交互,例如在被告知刚刚创建了该blob之后读取存储blob。
消费者的兴趣所在会激励生产者在事件中包含哪些信息。
-
中间件将事件从生产者路由到消费者,或者转发到其他中间件。生成事件的应用程序可能会将因消费者需求而产生的某些任务委托给中间件:
- 针对多个类别之一或原始事件上下文,管理许多并发感兴趣的消费者
- 代表消费者根据事件的类别或原始上下文处理过滤条件。
- 转码,如从JSON解码后编码为MsgPack
- 改变事件结构的转换,例如从专有格式到CloudEvents的映射,同时保留事件的身份和语义完整性。
- 即时“推送式”发送给感兴趣的消费者。
- 存储最终交付的事件,由消费者的(“pull”),或者在延迟之后由中间件的(“push”)发起提取。
- 监视事件内容或事件流以进行监视或诊断。
为了满足这些需求,中间件将对以下内容感兴趣:
- 可用于事件的分类或上下文化的元数据鉴别器,使得消费者可以表达对一个或多个这样的类或上下文的兴趣。例如,消费者可能对与文件存储帐户内的特定目录相关的所有事件感兴趣。
- 元数据鉴别器,允许区分该类型或上下文的特定事件的主题。例如,消费者可能想要过滤掉与以“.jpg”结尾的新文件相关的所有事件(文件名是"新文件"事件的主题),用于描述它已经注册为感兴趣的文件存储帐户内的特定目录的上下文。
- 用于编码事件及其数据的指示符。
- 事件及其数据的结构布局(模式)的指示符。
生产者的事件是否可通过中间件消费,是生产者的委托选择。
在实践中,中间件可以在改变事件的语义含义时承担生成器的角色,在基于事件采取行动时承担消费者的角色,或在路由事件不进行语义更改时承担中间件的角色。
-
框架和其他抽象使得与事件平台基础设施的交互更简单,并且通常为多个事件平台基础设施提供通用API区域。
-
框架通常用于将事件转换为对象图,并将事件分派给某些特定的用户代码处理或用户规则,以允许使用应用程序对原始上下文和特定主题中的特定类型的事件作出反应。
-
框架最感兴趣的是它们抽象的平台上的语义元数据共性,因此可以统一处理类似的活动。
对于体育应用程序,使用该框架的开发人员可能对来自联盟中的球队(感兴趣的topic)的今天的游戏(subject)的所有事件感兴趣,但是想要处理与“substitution”的报告不同的“goal”的报告。为此,框架将需要一个合适的元数据鉴别器,使其不必理解事件细节。
-
符号和术语
符号约定
本文档中的关键词 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, 和 “OPTIONAL” 按照 RFC 2119 中的描述进行解释。
为了清楚起见,当一个功能被标记为 “可选/OPTIONAL “时,这意味着消息的生产者和消费者都可以选择支持该功能。换句话说,如果生产者愿意,可以选择将该功能包含在消息中,如果消费者愿意,可以选择支持该功能。那么不支持该功能的消费者就会默默地忽略消息中的那部分内容。生产者需要为消费者忽略该功能的情况做好准备。中间人应该转发选择性属性。
术语
该规范定义了以下术语:
Occurrence/发生
“发生/occurrence"是指在软件系统运行过程中捕捉到的事实陈述。这可能是由于系统引发的信号或系统观察到的信号、状态变化、计时器过期或任何其他值得注意的活动而发生。例如,设备可能因为电池电量不足而进入警报状态,或者虚拟机即将执行预定的重启。
Event/事件
“事件/event"是表示发生(occurrence)及其上下文的数据记录。事件被从事件生产者(源)路由到感兴趣的事件消费者。可以根据事件中包含的信息进行路由,但事件不会确定具体的路由目的地。事件将包含两类信息:事件数据(Event Data)代表发生(occurrence),而上下文元数据(Context metadata)提供关于发生(occurrence)的上下文信息。一个发生(occurrence)可能会产生多个事件。
Producer/生产者
“Producer/生产者”是特定实例、过程或设备,用于创建描述 CloudEvent 的数据结构。
Source/来源
“Source/来源”是指发生(occurrence)出现的上下文。在一个分布式系统中,它可能由多个Producer组成。如果一个源不知道CloudEvents,外部生产者代表源创建CloudEvents。
Consumer/消费者
“Consumer/消费者"接收到事件,并对其采取行动。它使用上下文和数据来执行一些逻辑,这可能导致新事件的发生。
中介机构
“中介机构/Intermediary”接收包含事件的消息,目的是将其转发给下一个接收者,而这个接收者可能是另一个中间人或消费者。中间人的一个典型任务是根据上下文中的信息将事件转发到接收者。
Context/上下文
上下文元数据将被封装在上下文属性(Context Attributes)中。工具和应用程序代码可以使用这些信息来识别事件与系统的各个方面或与其他事件的关系。
数据
有关事件(即payload/有效载荷)的特定领域信息。这可能包括有关发生(occurrence)的信息、有关被更改的数据的详细信息或更多信息。有关更多信息,请参阅事件数据(Event Data)部分。
事件格式 / Event Format
事件格式指定了如何将 CloudEvent 序列化为字节序列。独立的事件格式(如 JSON 格式)可指定独立于任何协议或存储介质的序列化。协议绑定可以定义依赖于协议的格式。
Message/消息
事件通过消息从源(Source)传输到目的地(Destination)。
“结构化模式报文/structured-mode message” 是指使用独立的事件格式对事件进行完全编码并存储在消息主体中。
“二进制模式报文/binary-mode message” 是指事件数据(event data)存储在消息体中,事件属性作为消息元数据的一部分存储。
Data/数据
关于发生/occurrence(如有效载荷)的领域特定信息。这可能包括有关发生的信息,有关已更改数据的详细信息或更多。
Protocol/协议
消息可以通过各种行业标准协议(例如HTTP,AMQP,MQTT,SMTP),开源协议(例如Kafka,NATS)或平台/供应商特定协议(AWS Kinesis,Azure Event Grid)来传递。
Protocol Binding/协议绑定
协议绑定描述了事件如何通过给定协议发送和接收事件,特别是事件如何映射到该协议中的消息。
上下文属性
符合本规范的每个 CloudEvent 必须包含上下文属性,而且要指定为 REQUIRED,可以包含一个或多个 OPTIONAL 上下文属性,也可以包含一个或多个扩展属性。
这些属性在描述事件的同时,被设计为可以 独立于事件数据进行序列化。这使得它们可以在目的地被检查,而不需要对事件数据进行反序列化。
属性命名约定
CloudEvents 规范定义了对各种协议和编码的映射,随附的 CloudEvents SDK 针对各种运行时和语言。其中有些将元数据元素视为大小写敏感,而另一些则不敏感,而且单个 CloudEvents 可能会通过多个跳转来实现,中间涉及协议、编码和运行时。因此,本规范限制了所有属性的可用字符集,以防止大小写敏感问题或与通用语言中标识符的允许字符集冲突。
CloudEvents 属性名称必须由 ASCII 字符集中的小写字母(‘a’至’z’)或数字(‘0’至'9’)组成。属性名称应具有描述性和简洁性,长度不得超过 20 个字符。
类型系统
以下是可用于属性中的抽象数据类型。这些类型中的每个类型都可以由不同的事件格式和协议元数据字段来表示。本规范为每个类型定义了一个标准的字符串编码,所有的实现都必须支持。
-
Boolean
- 值为 “true “或 “false “的布尔值。- 字符串编码:大小写敏感的 “true “或 “false” 值。
-
Integer
-2,147,483,648到+2,147,483,647之间的整数。这是一个有符号的、32位的、二进制编码的范围。事件格式不一定要使用这个编码,但它们必须只使用这个范围内的整数值。- 字符串编码: 根据RFC 7159,第6节,JSON号码的整数部分。
-
String
- 允许的Unicode字符序列。以下字符不允许使用。-
U+0000-U+001F 和 U+007F-U+009F (两个范围都包括在内)中的 “控制字符”,因为大多数字符没有约定的含义,有些字符,如 U+000A (换行符),在HTTP 头等上下文中不能使用。
-
代码点被Unicode识别为非字符。
-
U+D800-U+DBFF和U+DC00-U+DFFF,这两个范围都包括在内,除非正确地成对使用。因此,(在JSON符号中)"\uDEAD “是无效的,因为它是一个未配对的代名词,而”\uD800\uDEAD “是合法的。
-
-
Binary
- 字节序列。- 字符串编码: Base64 编码,按照 RFC4648 的规定进行编码。
-
URI–绝对统一的资源标识符。
- 字符串编码:RFC4648中定义的绝对统一资源标识符。字符串编码:RFC 3986 第 4.3 节中定义的绝对 URI。
-
URI-reference - 统一资源标识符引用。
- 字符串编码:RFC 3986 第4.3 节中定义的URI-reference。URI-reference - RFC 3986 第4.1 节中定义的URI-reference。
-
Timestamp - 使用Gregorian Calendar的日期和时间表达式。
- 字符串编码:RFC 3339。
所有的上下文属性值必须是上面列出的类型之一。属性值可以以本地类型或标准字符串的形式呈现。
表示 CloudEvent 或任何扩展的强类型编程模型必须能够将常规字符串编码转换为最适合抽象类型的运行时/语言原生类型。
例如,在给定的实现中,时间属性可以用语言的本机日期时间类型来表示,但必须提供 RFC3339 字符串,并且在映射到 HTTP 消息的报文头时,必须可转换为 RFC3339 字符串。
同样,CloudEvents 协议绑定或事件格式实现也必须能够在编码或协议元数据字段中将标准字符串编码转换为相应的数据类型。
时间戳类型的属性值确实可以作为一个字符串通过多次跳转,并且只在生产者和最终消费者那里以本地运行时/语言类型的形式实现。时间戳也可能被路由为本地协议类型,并可能在生产者和消费者端被映射到/从各自的语言/运行时类型,而永远不会以字符串的形式实现。
序列化机制的选择将决定上下文属性和事件数据的序列化方式。例如,在JSON序列化的情况下,上下文属性和事件数据可能同时出现在同一个JSON对象中。
必须的属性
以下属性必须在所有 CloudEvents 中出现。
id
- Type:
String
- 描述: 标示事件。生产者必须确保
source
+id
对于每个独立的事件都是唯一的。如果一个重复的事件被重新发送(例如,由于网络错误),它可能有相同的id。消费者可能会认为 source 和 id 相同的事件是重复的。 - Examples:
- 由生产者维护的事件计数器
- UUID
- Constraints:
- REQUIRED
- 必须是一个非空字符串
- 必须在生产者范围内是唯一的
source
-
Type:
URI-reference
-
Description: 标示事件发生的上下文。通常包括事件源的类型、发布事件的组织或产生事件的过程等信息。URI 中编码的数据背后的确切语法和语义由事件生产者定义。
生产者必须确保
source
+id
对于每个独立的事件都是唯一的。应用程序可以为每个独立的生产者分配一个唯一的source,这样就很容易产生唯一的ID,因为没有其他生产者会有相同的source。应用程序可以使用 UUIDs、URNs、DNS 权限或特定于应用程序的方案来创建唯一的source标识符。
一个源也可以包括多个的生产者。在这种情况下,生产者必须合作,确保
source
+id
对于每个独立的事件都是唯一的。 -
Constraints:
- REQUIRED
- MUST be a non-empty URI-reference
- 推荐使用绝对URI
-
Examples
- 全网唯一的URI,具有DNS权限。
- 通用唯一的URN与UUID
- urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66
- 应用特定的标识符
- /cloudevents/spec/pull/123
- /sensors/tn-1234567/alerts
- 1-555-123-4567
specversion
- Type:
String
- Description: 事件所使用的 CloudEvents 规范的版本。该版本可用于解释上下文。兼容的事件制作者在引用此版本的规范时,必须使用 1.0 的值。
- Constraints:
- REQUIRED
- MUST be a non-empty string
type
- Type:
String
- Description: 该属性包含一个描述事件类型的值,描述与起源事件相关的事件类型。该属性通常用于路由、可观察性、策略执行等。该属性的格式是由生产者定义的,可能包括类型的版本等信息–更多信息请参见Primer中的属性版本化。
- Constraints:
- REQUIRED
- MUST be a non-empty string
- 应该以一个反转的DNS名称为前缀。前缀域决定了定义这个事件类型的语义的组织。
- Examples
- com.github.pull.create
- com.example.object.delete.v2
可选属性
以下为可在 CloudEvents 中出现的可选属性。有关 OPTIONAL 定义的更多信息,请参阅 Notational Conventions 部分。
datacontenttype
-
Type:
String
per RFC 2046 -
Description: data 值的内容类型。该属性使数据可以携带任何类型的内容,其格式和编码可能与所选事件格式不同。例如,使用JSON信封格式渲染的事件可能会携带一个XML有效载荷的数据,这个属性被设置为 “application/xml “就会通知消费者。不同的数据内容如何渲染不同的数据内容类型值的规则在事件格式规范中定义了;例如,JSON事件格式在3.1节中定义了这种关系。
对于一些二进制模式的协议绑定,该字段直接映射到各自协议的内容类型元数据属性。二进制模式和内容类型元数据映射的规范性规则可以在相应的协议中找到。
在某些事件格式中,datacontententtype属性可能会被省略。例如,如果一个JSON格式的事件没有datacontententtype属性,那么就意味着数据是符合 “application/json “媒体类型的JSON值。换句话说:一个没有datacontententtype的JSON格式事件与一个datacontenttype=“application/json “的事件完全等同。
当将一个没有datacontenttype属性的事件消息翻译成不同的格式或协议绑定时,目标datacontenttype应该明确地设置为源的隐含datacontenttype。
-
Constraints:
- OPTIONAL
- 如果存在,必须遵守RFC 2046中规定的格式。
-
For Media Type examples see IANA Media Types
dataschema
- Type:
URI
- 指明 data 所遵循的 schema。对模式的不兼容的更改应该通过不同的URI来反映。更多信息请参见Primer中的属性版本化。
- Constraints:
- OPTIONAL
- If present, MUST be a non-empty URI
subject
-
Type:
String
-
Description: 描述了事件生产者(通过 source 标识)上下文中的事件主题。在发布-订阅场景中,订阅者通常会订阅由源发出的事件,但如果源上下文有内部子结构,仅有源标识符可能不足以作为任何特定事件的限定符。
在上下文元数据中识别事件的主体(而不是仅在 data 有效载荷中),这在中间件无法解释 data 内容的通用订阅过滤场景中特别有帮助。在上面的例子中,订阅者可能只对以'.jpg’或'.jpeg’结尾的blob感兴趣,而主题属性允许为该事件的子集构造一个简单有效的字符串后缀过滤器。
-
Constraints:
- OPTIONAL
- If present, MUST be a non-empty string
-
Example:
- 当在blob-存储容器内创建新的blob时,订阅者可能会注册兴趣。在这种情况下,事件 source 标识了订阅范围(存储容器),type 标识了 “blob创建 “事件,id唯一标识了事件实例,以区分已创建的相同名称的blob的单独出现;新创建的blob的名称在 subject中携带。
- source:https://example.com/storage/tenant/container
- subject: mynewfile.jpg
- 当在blob-存储容器内创建新的blob时,订阅者可能会注册兴趣。在这种情况下,事件 source 标识了订阅范围(存储容器),type 标识了 “blob创建 “事件,id唯一标识了事件实例,以区分已创建的相同名称的blob的单独出现;新创建的blob的名称在 subject中携带。
time
- Type:
Timestamp
- Description: 事件发生的时间戳。如果无法确定事件发生的时间,则该属性可以由 CloudEvents 生产者设置为其他时间(如当前时间),但同一源的所有生产者在这方面必须保持一致。换句话说,它们要么都使用实际发生的时间,要么都使用相同的算法来确定所使用的值。
- Constraints:
- OPTIONAL
- If present, MUST adhere to the format specified in RFC 3339
扩展上下文属性
CloudEvent 可包含任意数量的具有不同名称的附加上下文属性,称为 “扩展属性”。扩展属性必须遵循与标准属性相同的命名惯例,并使用与标准属性相同的类型系统。扩展属性在本规范中没有定义的含义,它们允许外部系统将元数据附加到事件中,就像HTTP自定义头一样。
扩展属性总是按照与标准属性一样的绑定规则进行序列化。然而,本规范并不妨碍扩展将事件属性值复制到消息的其他部分,以便与同样处理消息的非CloudEvents系统进行交互。这样做的扩展规范应该指定如果复制的值与 cloud event 序列化的值不同,接收者应该如何解释消息。
定义扩展
请参阅 CloudEvent 属性扩展,了解有关扩展的使用和定义的更多信息。
扩展的定义应该完全定义属性的所有方面,例如,其名称、类型、语义和可能的值。新的扩展定义应该使用一个描述性足够强的名称,以减少与其他扩展名称碰撞的可能性。特别是,扩展作者应该检查文档中的扩展文档中的已知扩展集–不仅仅是检查可能的名称冲突,还应该检查可能感兴趣的扩展。
许多协议支持发送者包含附加元数据的能力,例如作为 HTTP 头文件。虽然 CloudEvents 接收方没有被强制要求处理和传递这些元数据,但建议他们通过某种机制来处理和传递这些元数据,以表明它们是非 CloudEvents 元数据。
下面是一个例子,说明了对附加属性的需求。在许多 IoT 和企业用例中,一个事件可以在无服务器的应用程序中使用,该事件可以在多个类型的事件中执行操作。为了支持这样的用例,事件生产者需要在 “上下文属性 “中添加额外的身份属性,事件消费者可以使用这些属性将该事件与其他事件关联起来。如果这种身份属性恰好是事件 “数据 “的一部分,事件生产者也将把身份属性添加到 “上下文属性 “中,这样,事件消费者就可以方便地访问这些信息,而不需要解码和检查事件数据。这样的身份属性也可以用来帮助中间网关确定如何路由事件。
事件数据
正如术语 “Data “所定义的那样,CloudEvents 可包括与事件发生相关的领域特定信息。如果存在,此信息将被封装在 data 中。
- 描述:事件有效载荷(Payload)。本规范不对该信息的类型进行任何限制。它被编码成由datacontententtype属性指定的媒体格式(例如:application/json),并且当这些相应的属性存在时,它将遵循dataschema格式。
- Constraints:
- OPTIONAL
大小限制
在许多场景中,CloudEvents 将通过一个或多个通用中间人转发,每个中间人都可能会对转发事件的大小进行限制。CloudEvents 也可能会被转发到消费者,比如嵌入式设备,这些设备受存储或内存限制,因此在处理大的单一事件时可能会很吃力。
事件的 “大小"是指事件的线上(wire-size)大小,包括事件的线上传输的每一个比特:协议帧元数据、事件元数据和事件数据,基于所选的事件格式和所选的协议绑定。
如果应用配置要求在不同的协议之间转发事件,或要求对事件进行重新编码,则应考虑应用所使用的最有效的协议和编码,以符合这些大小限制。
- 中间商必须转发大小为64KByte或以下的事件。
- 消费者应接受至少64 KByte大小的事件。
实际上,这些规则将允许生产者安全地发布大小不超过64KB的事件。这里的 “安全 “指的是,一般来说,期望事件被所有中间人接受并转发是合理的。出于本地的考虑,它是否愿意接受或拒绝该大小的事件,是在任何特定消费者的控制范围内。
一般来说,CloudEvents 发布者应该通过避免在事件有效载荷中嵌入大型数据项来保持事件的紧凑性,而是使用事件有效载荷链接到这些数据项。从访问控制的角度来看,这种方法还可以让事件的分布范围更广,因为通过解析链接访问事件相关的细节,可以实现差异化的访问控制和选择性的披露,而不是直接将敏感细节嵌入事件中。
隐私和安全
互操作性是本规范背后的主要驱动力,要实现这样的行为,需要将一些信息公开,导致信息泄露的可能性。
请考虑以下几点,以防止不经意间的泄漏,特别是在利用第三方平台和通信网络时。
-
上下文属性
敏感信息不应在上下文属性中携带或表示。
CloudEvent 生产者、消费者和中间人可以审查并记录上下文属性。
-
Data
领域特定 event data 应进行加密,以限制受信任方的可见性。用于这种加密的机制是生产者和消费者之间的协议,因此不属于本规范的范围。
-
Protocol Bindings
应采用协议级的安全性,以确保CloudEvents的可信和安全交换。
示例
下面的示例展示了一个被序列化为JSON的CloudEvent:
{
"specversion" : "1.0",
"type" : "com.github.pull.create",
"source" : "https://github.com/cloudevents/spec/pull",
"subject" : "123",
"id" : "A234-1234-1234",
"time" : "2018-04-05T17:31:00Z",
"comexampleextension1" : "value",
"comexampleothervalue" : 5,
"datacontenttype" : "text/xml",
"data" : "<much wow=\"xml\"/>"
}
5 - HTTP Protocol Binding
备注:内容来自 https://github.com/cloudevents/spec/blob/v1.0/http-protocol-binding.md
摘要
CloudEvents 的 HTTP 协议绑定定义了如何将事件映射到 HTTP 1.1 请求和响应消息。
1. 简介
CloudEvents是事件的结构和元数据描述的标准化且与协议无关的定义。该规范定义了如何在HTTP 1.1请求和响应消息中使用CloudEvents规范中定义的元素。
1.1 Conformance
本文档中的关键词 “MUST”、“MUST NOT”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY “和 “OPTIONAL “等,应按RFC2119中的解释。
1.2 与 HTTP 的关系
本规范没有规定约束特定HTTP方法的使用或处理规则,也没有约束用于传输或请求事件的HTTP目标资源。
事件可以通过所有支持有效载荷体传输的标准或应用程序定义的HTTP请求方法来传输。事件也可以在HTTP响应中以及与允许有效载荷体传输的所有HTTP状态码一起传输。
这里所有显示HTTP方法、HTTP目标URI和HTTP状态码的例子都是非规范性的说明。
本规范也同样适用于与 HTTP 1.1语义兼容的 HTTP/2(RFC7540)。
注意:也适用于HTTP/2
1.3 内容模式
本规范定义了传输事件的三种内容模式:二进制(binary)、结构化(structured)和批量(batched)。每个符合规范的实现都应该支持二进制(binary)和结构化(structured)模式。
在二进制内容模式下,事件 data 的值被放置到HTTP请求或响应的主体(body)中,并在HTTP Content-Type header中以 datacontenttype属性的值声明其媒体类型;所有其他事件属性都被映射到HTTP头。
在结构化内容模式下,事件元数据属性和事件数据被放置到HTTP请求或响应body中,使用事件格式。
在批量内容模式中,多个事件使用支持批量的事件格式,分批放入单个HTTP请求或响应body中。
1.4 事件格式
与结构化内容模式一起使用的事件格式,定义了事件如何以特定的数据格式表达。本规范的所有实现必须支持非批处理的JSON事件格式,但也可以支持任何其他格式,包括专有格式。
事件格式可以额外定义事件批处理的表达方式。这些格式可以与批处理内容模式一起使用。
1.5 安全
本规范没有为HTTP引入任何新的安全特性,也没有规定要使用特定的现有特性。本规范同样适用于TLS上的HTTP。
2. CloudEvents 属性的使用
本规范没有进一步定义任何核心 CloudEvents 事件属性。
此映射是为了防止变化(包括事件属性的添加和删除),并适应供应商对事件元数据的扩展。
2.1 datacontententtype 属性
datacontententtype属性被认为包含一个符合RFC2046的媒体类型表达式。
2.2 data
data 被假定为包含由 datacontenttype 属性声明的不透明的应用数据。
应用程序可以自由地以其选择的任何内存中的表示方式来保存信息,但是由于该值是按照本规范中的定义被转接到HTTP中的,因此假设 data 的值是以字节序列的形式提供的。
例如,如果声明的 datacontenttype 为 application/json;charset=utf-8,则期望 data 值以 UTF-8 编码的JSON文本形式提供给HTTP。
3. HTTP消息映射
HTTP请求和响应消息的事件绑定是相同的。
内容模式是由事件的发送方选择的,发送方可以是请求方或响应方。可能允许使用特定模式请求事件的手势可能是由应用程序定义的,但这里没有定义。除非被邀约,否则不能使用批量模式,而且手势应该允许接收方选择最大的批处理量。
事件的接收方可以通过检查 Content-Type header 的值来区分这三种模式。如果该值前缀为 CloudEvents 媒体类型 application/cloudevents
,表示使用已知的事件格式,则接收方使用结构化模式。如果该值前缀为 application/cloudevents-batch
,则接收器使用批处理模式。否则,则默认为二进制模式。
备注:默认是使用二进制模式
如果接收器检测到 CloudEvents 媒体类型,但它无法处理的事件格式(例如 application/cloudevents+avro),它仍然可以将事件作为二进制模式处理,并将其转发到另一方。
3.1. 二进制内容模式
二进制的内容模式可以容纳任何形状的事件数据,并允许高效传输,无需转码。
3.1.1. HTTP Content Type
对于二进制模式,HTTP Content-Type header值对应于(必须从 CloudEvents datacontenttype 属性中填充或写入)CloudEvents datacontenttype 属性。请注意 ce-datacontenttype HTTP 标头不能也存在于消息中。
3.1.2. 事件数据编码
data 字节序列作为HTTP报文Body。
3.1.3. Metadata headers
所有其他 CloudEvents 属性(包括扩展)必须单独映射到不同的 HTTP 消息头,并从不同的 HTTP 消息头中映射。
定义了自己属性的 CloudEvents 扩展可以为这些属性定义二级映射到 HTTP 头,特别是当特定属性需要与 HTTP 特性或其他有明确 HTTP 头绑定的规范保持一致时。请注意,这些属性还必须作为带有 ce 前缀的 HTTP 标头出现在 HTTP 报文中,如 HTTP 标头名称中所述。
3.1.3.1. HTTP Header Names
除注明的情况外,所有 CloudEvents 上下文属性(包括扩展)都必须映射到与属性名称相同但前缀为 ce 的 HTTP header中。
Examples:
* `time` maps to `ce-time`
* `id` maps to `ce-id`
* `specversion` maps to `ce-specversion`
注意:根据HTTP规范,header name是不区分大小写的。
3.1.3.2. HTTP header值
每个 HTTP header的值由相应属性类型的标准字符串表示法构建。
某些 CloudEvents 元数据属性可包含任意 UTF-8 字符串内容,根据 RFC7230 第 3 节,HTTP 标头必须仅使用 US-ASCII 字符集中的可打印字符,并由 CRLF 序列终止,标头值周围有可选的空白。
在应用[RFC7230,第3.2.6节][RFC7230-3-2s6]中描述的 header 编码规则之前,必须按照RFC3986,第2.4节中描述的百分比编码,对字符串值进行百分比编码。
将 HTTP 报文解码为 CloudEvent 时,必须反向应用这些规则 – RFC7230 第 3.2.6 节对 ASCII 字符串进行解码,然后按照 RFC3986 第 2.4 节中的描述进行单轮百分比解码,以生成有效的 UTF-8 字符串。(注意,应用百分比解码的次数不正确可能导致报文损坏或安全问题)。
3.1.4. Examples
这个例子显示了带有HTTP POST请求的事件与的二进制模式映射:
POST /someresource HTTP/1.1
Host: webhook.example.com
ce-specversion: 1.0
ce-type: com.example.someevent
ce-time: 2018-04-05T03:56:24Z
ce-id: 1234-1234-1234
ce-source: /mycontext/subcontext
.... further attributes ...
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
... application data ...
}
这个例子显示了包含事件的响应:
HTTP/1.1 200 OK
ce-specversion: 1.0
ce-type: com.example.someevent
ce-time: 2018-04-05T03:56:24Z
ce-id: 1234-1234-1234
ce-source: /mycontext/subcontext
.... further attributes ...
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
... application data ...
}
3.2. 结构化内容模式
结构化的内容模式将事件元数据和数据保持在有效载荷中,使得同一事件可以在多个路由跳转、多协议之间简单转发。
3.2.1. HTTP内容类型
HTTP内容类型头必须设置为事件格式的媒体类型。
JSON 格式的示例。
Content-Type: application/cloudevents+json; charset=UTF-8
3.2.2. 事件数据编码
所选择的事件格式定义了所有属性和数据的表示方式。
然后按照事件格式规范对事件元数据和数据进行渲染,最后得到的数据成为HTTP报文body。
3.2.3. metadata header
实现可以包含与二进制模式定义的相同的 HTTP 标头。
所有 CloudEvents 元数据属性都必须映射到有效载荷(Payload)中,即使它们也已经映射到 HTTP header中了。
3.2.4. 示例
这个例子显示了一个JSON事件格式编码的事件,用PUT请求发送:
PUT /myresource HTTP/1.1
Host: webhook.example.com
Content-Type: application/cloudevents+json; charset=utf-8
Content-Length: nnnn
{
"specversion" : "1.0",
"type" : "com.example.someevent",
... further attributes omitted ...
"data" : {
... application data ...
}
}
这个例子显示了一个响应中返回的JSON编码的事件:
HTTP/1.1 200 OK
Content-Type: application/cloudevents+json; charset=utf-8
Content-Length: nnnn
{
"specversion" : "1.0",
"type" : "com.example.someevent",
... further attributes omitted ...
"data" : {
... application data ...
}
}
3.3. 批量内容模式
在批量内容模式下,多个事件被批量到一个HTTP请求或响应体中。选择的事件格式必须定义如何表示一个批次。基于JSON格式(任何兼容的实现都必须支持JSON格式),JSON Batch格式是一种支持批处理的事件格式。
3.3.1. HTTP 内容类型
HTTP Content-Type头必须设置为事件格式的媒体类型。
JSON Batch 格式的示例。
Content-Type: application/cloudevents-batch+json; charset=UTF-8
3.3.2. 事件数据编码
所选的事件格式定义了一批事件和所有事件属性和数据的表示方式。
然后根据事件格式规范对事件批进行渲染,结果数据将成为HTTP消息主体。
该批事件可以是空的。所有批处理的 CloudEvents 必须具有相同的 specversion 属性。其他属性可能不同,包括 datacontententtype 属性。
3.2.3 Examples
This example shows two batched CloudEvents, sent with a PUT request:
PUT /myresource HTTP/1.1
Host: webhook.example.com
Content-Type: application/cloudevents-batch+json; charset=utf-8
Content-Length: nnnn
[
{
"specversion" : "1.0",
"type" : "com.example.someevent",
... further attributes omitted ...
"data" : {
... application data ...
}
},
{
"specversion" : "1.0",
"type" : "com.example.someotherevent",
... further attributes omitted ...
"data" : {
... application data ...
}
}
]
This example shows two batched CloudEvents returned in a response:
HTTP/1.1 200 OK
Content-Type: application/cloudevents-batch+json; charset=utf-8
Content-Length: nnnn
[
{
"specversion" : "1.0",
"type" : "com.example.someevent",
... further attributes omitted ...
"data" : {
... application data ...
}
},
{
"specversion" : "1.0",
"type" : "com.example.someotherevent",
... further attributes omitted ...
"data" : {
... application data ...
}
}
]
6 - Json事件格式
备注:内容来自 https://github.com/cloudevents/spec/blob/v1.0/json-format.md
2. Attributes
本节定义了 CloudEvents 属性如何映射到 JSON。本规范没有明确映射每个属性,但提供了一个通用映射模型,该模型适用于所有当前和未来的 CloudEvents 属性(包括扩展)。
为明确起见,扩展属性使用与规范定义的属性相同的规则进行序列化。这包括其语法和在 JSON 对象中的位置。特别是,扩展作为顶层 JSON 属性放置。扩展必须被序列化为顶层JSON属性。这个设计决定有很多原因,在Primer中会详细介绍。
2.2. Type System Mapping
扩展规范可以为其定义的属性值定义二次映射规则,但必须包括之前定义的主映射。
例如,属性值可能是在 CloudEvents 以外的标准中定义的数据结构,具有正式的 JSON 映射,如果不保留原始格式,可能会有翻译错误或信息丢失的风险。
定义了 JSON 次要映射规则的扩展规范,以及对该规范的任何修订,都必须为提交或修订时属于 CloudEvents 核心的所有其他事件格式定义明确的映射规则。
如果需要,例如在解码地图时,CloudEvents 类型可以通过使用映射表中的规则进行推理来确定,其中唯一潜在的模糊 JSON 数据类型是字符串。当满足映射规则时,该值与相应的 CloudEvents 类型兼容。
3. Envelope
每个 CloudEvents 事件可以完全表示为一个 JSON 对象。
这种表示方式必须使用媒体类型 application/cloudevents+json。
给定事件中的所有 REQUIRED 和所有未省略的 OPTIONAL 属性必须成为 JSON 对象的成员,相应的 JSON 对象成员名称与属性名称相匹配,并且成员的类型和值使用类型系统映射。
3.1. 对 “data"的处理
在采取行动之前,JSON序列化器必须首先确定数据内容的运行时数据类型。
如果实现确定数据类型为二进制,则必须将值表示为包含Base64编码的二进制值的JSON字符串表达式,并使用成员名data_base64将其存储在JSON对象中。
对于任何其他类型,实现必须将数据值转换为JSON值,并使用成员名data_base64来存储在JSON对象中。
由此可见,在 JSON 序列化的 CloudEvent 中,数据和 data_base64 成员的使用是相互排斥的。
当从 JSON 中解串化 CloudEvents 时,data_base64 成员的存在清楚地表明该值是 Base64 编码的二进制数据,序列化器必须将其解码为二进制的运行时数据类型。当数据成员存在时,它将使用默认的JSON类型映射来解码,用于使用的运行时。
与属性不同的是,根据类型系统映射,值类型被限制为字符串,而产生的数据成员JSON值是不受限制的,可以包含任何有效的JSON。
7 - SDK需求
备注:内容来自 https://github.com/cloudevents/spec/blob/master/SDK.md
本文档的目的是描述针对CloudEvents的新软件开发工具包(SDK)的最低要求。这些SDK的设计和实施是为了增强和加快CloudEvents的集成。作为社区工作的一部分,CloudEvents团队承诺支持和维护以下SDK。
本文档旨在为 SDK 作者提供指导和要求。本文档旨在与 CloudEvents 规范保持同步更新。
技术需求
每个SDK必须满足这些要求。
- 支持CloudEvents 的里程碑版本和正在进行的开发版本。
- 将Canonical Event编码为特定于传输的编码消息。
- 将特定于传输的编码消息解码为Canonical事件。
- 熟练使用编程语言。
- 使用当前的语言版本。
- 支持结构化和二进制编码的HTTP传输渲染。
对象模型结构准则
每个SDK将提供一个通用的CloudEvents类/对象/结构,该类/对象/结构表示事件的典型形式。
该 SDK 应使用户能够绕过 CloudEvents Event 对象的特定传输编码和解码。对象的一般流程应该是:
Event (-> Message) -> Transport
和
Transport (-> Message) -> Event
不需要SDK来实现传输的包装器,重点应该是允许编程模型与高层次的Event对象一起工作,并提供工具将Event转化成可以与所选的实现传输一起使用的东西。
在高层次上,SDK需要能够帮助完成以下任务。
- 组合事件。
- 编码事件,给定传输和编码(如果适当的话,将其编码为传输消息)。
- 解码特定于传输的消息、请求或响应(如果适当的话,到一个传输消息)为事件。
组合事件
提供一种方便的方法,既可以组成单一消息,也可以组成许多消息。实现者将需要一种方法来快速建立事件数据并将其转换为CloudEvents编码的事件。在实践中,事件的组成往往有两个方面。
-
事件创建
“我有一个格式不是CloudEvent的数据,我想让它成为CloudEvent。”
-
事件变化
“我有一个CloudEvents格式化的事件,我需要将它变成不同的事件。” “我有一个CloudEvents格式化的事件,我需要修改事件。”
对于SDK语言来说,事件的创建是非常习以为常的。
事件变化往往用访问器模式来解决,比如getters和setter。但是可以利用直接的 key 访问,也可以利用命名的 key 访问器函数。
无论是哪种情况,都必须有一个方法根据参数设置来验证生成的Event对象,最重要的是CloudEvents规范版本。
对事件进行编码/解码
每个SDK都支持对事件进行编码和解码。结构化编码是最容易支持的,因为它只是json,但二进制编码对于每个传输方式来说是相当定制的。
数据
从事件中访问数据有一些考虑,事件可以被编码成base64形式,作为结构化数据,或者像json这样的线上格式。一个SDK必须提供一种方法来将这些格式的数据解压成原生格式。
扩展
支持CloudEventss的扩展又是成语,但镜像数据访问的方法似乎是可行的。
验证
验证必须在单个事件上进行。验证必须考虑到规格版本,以及每个版本的规格所提出的所有要求。
文档
每个SDK必须提供至少使用HTTP传输的例子。
- 组成事件。
- 对组成的事件进行编码和发送。
- 接收和解码事件。