领先一步
VMware 提供培训和认证,助您加速进步。
了解更多跨系统和平台的数据统一是 Cloud Event 规范 的一个独特而崇高的目标。随着它的日益普及,我们希望开发者和架构师不再需要担心如何处理来自不同系统和平台的各种事件。. . 但本文的目的不是重新讨论或重新证明 Cloud Events 的合理性。一个简单的 Google 搜索就能提供很多资料,帮助您回答“为什么选择 Cloud Events?”这个问题。本文以及后续关于该主题的帖子旨在分享一些想法以及我们在 Spring 所做的工作,以预测和应对 Cloud Events 的更广泛采用。
Message,即 EIP Message 的 Spring 实现,是一个足以表示 Cloud Event 的结构!这是我们在这里要构建的案例。如果属实,那么任何当前依赖 Spring Messaging 的框架或应用程序都将自动支持 Cloud Event 用例。所以。 . .
根据官方网站,Cloud Events是“以通用方式描述事件数据的规范”。
如果您阅读规范(它非常简单),您会很快意识到 Cloud Event 有效地定义了一个规范的、平台独立的数据结构,以统一的方式在系统和平台之间进行交换。该结构相当简单。它将一些有效载荷封装为 `data` 字段,并将附加元数据封装为 `attributes`(键/值结构)。`attributes` 本身又分为定义明确的元数据字段,称为 `attributes`(必需和可选),以及定义松散或未定义的字段,称为 `extension attributes`。
目前就这些。
现在,对于那些熟悉消息——企业集成模式的核心之一——以及其在Spring Messaging中的定义的人来说,你可能会说:这看起来非常熟悉!确实如此。
就像 Cloud Event 一样,Message 定义了一种规范的、平台独立的数据结构,用于在系统和平台之间以统一的方式进行交换。这种结构非常简单。它将一些有效负载封装为 `payload` 字段,将元数据封装为 `headers`(键/值结构)。
为什么这很重要?与任何其他技术一样,在 Spring 中为 Cloud Events 提供集成实际上是一个问题,即在其用户熟悉且众所周知的 Spring 习语和抽象范围内实现其概念所需的努力。这就是为什么 Message 会浮现在脑海中。鉴于它与 Cloud Event 规范定义的结构几乎完美匹配,“Message 能否成为 Spring 中表示 Cloud Event 的合适抽象?”因为,如果答案是“是”,那么目前依赖 Spring Messaging 的成千上万的框架和应用程序都可以自动支持 Cloud Event 用例,这意味着这些框架的用户以及框架本身都能够在规范定义的协议细节(例如属性前缀、类型系统等)范围内识别传入的 Cloud Event 实例并创建它们。
我们还需要研究一些典型的 Cloud Event 使用模式。我们这样做是为了隔离我们所说的功能性方面与非功能性(样板)方面。所以让我们描述其中一些
此列表是典型使用模式的一小部分子集,但它有助于阐明问题领域。它还有助于我们开始理解和隔离功能性与非功能性方面。有趣的是,大多数描述的模式都是非功能性方面的示例,经验丰富的 Spring 用户期望这些方面由框架处理。例如,虽然用户需要“生产一些东西”(功能性),但“将其封装到 Cloud Event 中”的部分应该由框架处理(非功能性)。同样原则也适用于消费 Cloud Event。虽然描述模糊,但它通常意味着用户可能只关心 Cloud Event 的数据部分,最有可能期望它以特定领域对象的形式出现,框架应该提取、转换和提供这些对象。所有这些再次是非功能性方面的示例。然后是 Cloud Event 属性及其前缀(例如,`ce_` 与 `ce-` 等)的问题,这些属性有效地描述了事件的来源或目的地,人们会期望框架也能处理这些问题,特别是考虑到功能实现者甚至可能不知道事件的来源或目的地。
十多年来,Spring 一直通过基于消息的框架成功支持转换、类型转换、路由、过滤以及更多消息传递模式(其中大部分由 企业集成模式 描述),数万个用户应用程序正在生产中运行。我们怎能忘记基础设施方面的担忧,例如连接性、会话和事务管理、发送和接收、重试、错误处理、恢复等等?在 Spring 中,我们的总体格言是:我们努力处理非功能性(样板)问题,只留下功能性(业务逻辑)问题给您。因此,对我们来说,在给定集成上下文中区分两者并尽可能多地外包给框架始终很重要。我们还公开了实用程序、库和配置选项,让您能够影响某些非功能性问题,因为出于各种原因可能仍然需要这样做。
那么,鉴于此,一个支持 Cloud Events 的典型 Spring 应用程序会是什么样子,尤其是在 Spring Boot 时代?
这是一个应用程序示例,它接收一个 Cloud Event 作为 HTTP 请求,并生成一个 Cloud Event 作为 HTTP 响应
@SpringBootApplication
public static class SampleApplication
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleApplication.class, args);
}
@Bean
Function<Person, Employee> hire() {
return person -> {
Employee employee = ...
return employee;
};
}
}
这是一个应用程序示例,它从 Apache Kafka 接收 Cloud Event 并将其发送到 RabbitMQ 消息代理
@SpringBootApplication
public static class SampleApplication
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleApplication.class, args);
}
@Bean
Function<Person, Employee> hire() {
return person -> {
Employee employee = ...
return employee;
};
}
}
我们省略了函数的实现细节,因为它们与主题无关。框架并不真正关心您做什么。它只关心您期望什么——输入——以及您生成什么——输出——并且该信息可从函数签名中获取。
然而,我确信这并非您所想,您可能想知道为什么我呈现的两个不同的应用程序实际上是相同的?以及哪里说明一个应用程序是 REST 端点而另一个是消息处理程序?为了回答这些问题,我们需要了解执行上下文,它来自您的应用程序类路径中可用的 Spring Boot 自动配置。因此,例如,要使第一个应用程序的描述为真,您需要在类路径中添加 `spring-cloud-function-web` 依赖项,它带来了将您的函数公开为 REST 端点所需的所有必要组件和额外的自动配置。至于第二个,我们可以简单地回退到我们已经为 Apache Kafka、AMQP、Solace、HTTP、AWS、Google 等提供的广泛的绑定器库。这些绑定器和相关的自动配置会将示例代码转换为消息处理程序。
消息是这种能力的核心,是 Spring 中所有活动部分都能理解的规范结构。它是一种能够清晰传达意图和期望的结构。它来自哪里?它将去往何处?谁发送了它?内容是什么?它是否代表一个 Cloud Event?如果是,它是二进制模式还是结构化模式?列表是无穷无尽的,但一个不变的事实是,消息作为一种结构和概念,能够很好地回答这些问题。考虑到这一点,Cloud Event 变成了另一种消息。Spring 框架可以像处理任何其他消息一样处理它,让您专注于业务逻辑,而不是底层细节。
因此,Message不仅是表示 Cloud Event 的一个足够好的结构,它也是在 Spring 中处理 Cloud Event 用例的正确抽象。我希望这一点明确,随着即将到来的 Cloud Event 对 Message 的支持,我们正在为任何依赖 Spring Messaging 的应用程序提供 Cloud Events 支持的道路上。
在后续帖子中,我们将涵盖几个 Spring 框架中即将推出的 Cloud Event 支持的技术细节,以及使用Cloud Event Java SDK与 Spring 进行 Cloud Event 集成。您现在也可以开始查看一些示例