简介
CloudEvents 是一种定义事件数据在云端应用之间如何交付的规范,这是由 Cloud Native Computing Foundation(CNCF)的 Serverless 工作小组开发的。通过提供统一的事件格式,CloudEvents 旨在简化跨服务、平台和供应商的事件交付。
CloudEvents位于CNCF全景图的”流和消息“
为什么要使用CloudEvents
在微服务和分布式系统中,事件驱动架构是一种常用模式,各种服务通过发布和订阅事件来进行交互。然而,由于各种服务可能使用不同的框架和平台,因此,一个通用的、跨平台的事件格式就变得尤为重要。这就是为什么需要使用 CloudEvents。
使用 CloudEvents 主要有以下优势:
- 标准化:CloudEvents 提供了一个标准的事件格式,包括一组必备的属性,比如source、type、id等,并定义如何编码和传输这些事件。这让不同的服务,即使在不同的环境和语言中,也能以一种一致的方式处理事件。
- 互操作性:由于 CloudEvents 是标准化的,它提高了互操作性。无论是在服务、云提供商、API 网关,甚至函数即服务(FaaS)平台之间,都可以通过 CloudEvents 进行交互。
- 简化开发:有了 CloudEvents,开发者可以不必关心不同服务和平台的特异性,只需要关注业务逻辑即可。这极大地简化了开发流程,提高了效率。
- 易于跟踪:CloudEvents 的标头中包括许多关于事件源、类型和 id 等信息,便于对事件进行追踪,提高运维效率。
总的来说,使用 CloudEvents 可以简化跨服务事件的处理流程,并提高互操作性和开发效率,是云原生开发中的一个重要工具。
CloudEvents格式规范
CloudEvents 是一个规范,定义了事件数据的标准和统一格式,以便在应用、服务和系统之间进行交互时保持一致性并提高互通性。CloudEvents 指定几个必要的属性以标记和描述事件数据,这些属性包括:
id: 事件的唯一标识符。
source: 定义事件发生的位置(通常是 URI)。
specversion: CloudEvents 规范的版本(例如,1.0)。
type: 描述事件类型的字符串,通常是由产生该事件的系统定义。
除了这些必须的属性外,CloudEvents 还有几个可选的属性,如:
datacontenttype: 描述 data 的媒体类型的字符串(例如,application/json)。
dataschema: 识别 data 内容使用的模式的 URI。
time: 事件产生的时间,记录为 RFC3339 时间戳。
subject: 描述 source 的主题。
消息的主体部分(data)可以包含特定于事件和其 type 的任何其他数据。具体的 data 结构完全由发件人和收件人之间的约定来确定。
以下是一个例子,它是一个 JSON 编码的 CloudEvents
{"specversion" : "1.0","type" : "com.github.pull.create","source" : "https://github.com/cloudevents/spec/pull/123","subject" : "123","id" : "A234-1234-1234","time" : "2018-04-05T17:31:00Z","comexampleextension1" : "value","datacontenttype" : "text/xml","data" : "<much wow=\"xml\"/>"
}
Demo
以spring boot为例,pom.xml加入cloud-events的sdk
<properties><cloudevents.version>2.3.0</cloudevents.version>
</properties>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--引入cloudevents依赖--><dependency><groupId>io.cloudevents</groupId><artifactId>cloudevents-spring</artifactId><version>${cloudevents.version}</version></dependency><dependency><groupId>io.cloudevents</groupId><artifactId>cloudevents-json-jackson</artifactId><version>${cloudevents.version}</version></dependency><dependency><groupId>io.cloudevents</groupId><artifactId>cloudevents-http-basic</artifactId><version>${cloudevents.version}</version></dependency>
</dependencies>
配置消息转换器CloudEventHandlerConfiguration.java
@Configuration
public class CloudEventHandlerConfiguration implements WebMvcConfigurer {@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(new CloudEventHttpMessageConverter());}
}
新建一个Controller用于测试
@RestController
public class CloudEventsDemoController {private static final ObjectMapper objectMapper = new ObjectMapper();@PostMapping("/echo2")public void ce(@RequestBody CloudEvent event) {// 此处集成jackson 以及cloudevent 数据格式,方便消息体处理CloudEvent event1 = CloudEventBuilder.from(event).withId(UUID.randomUUID().toString()).withSource(URI.create("https://spring.io/foos")).withType("io.spring.event.Foo").withData(event.getData().toBytes()).build();PojoCloudEventData<UserEntity> cloudEventData = mapData(event1,PojoCloudEventDataMapper.from(objectMapper,UserEntity.class));UserEntity user = cloudEventData.getValue();System.out.println(user.toString());System.out.println(event1);}@PostMapping("/echo")public ResponseEntity<UserEntity> echo(@RequestBody UserEntity foo, @RequestHeader HttpHeaders headers) {CloudEvent attributes = CloudEventHttpUtils.fromHttp(headers).withId(UUID.randomUUID().toString()).withSource(URI.create("https://cloudevent-demo/echo")).withType("io.spring.event.cloudevent-demo").build();HttpHeaders outgoing = CloudEventHttpUtils.toHttp(attributes);return ResponseEntity.ok().headers(outgoing).body(foo);}}
模拟客户端请求
curl -X POST -v -d '{"name": "linwj44", "age": 23}' \-H 'Content-type: application/octet-stream' \-H 'Ce-id: 1' \-H 'Ce-source: cloud-event-example' \-H 'Ce-type: happybirthday.myapplication' \-H 'Ce-specversion: 1.0' \http://localhost:8080/echo2