CloudEvents-云原生事件规范

简介

CloudEvents 是一种定义事件数据在云端应用之间如何交付的规范,这是由 Cloud Native Computing Foundation(CNCF)的 Serverless 工作小组开发的。通过提供统一的事件格式,CloudEvents 旨在简化跨服务、平台和供应商的事件交付。
CloudEvents位于CNCF全景图的”流和消息“
image.png

为什么要使用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 {
    @Override
    public 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
posted @ 2024-06-17 17:08  未来代码研究所  阅读(74)  评论(0编辑  收藏  举报