主要概念
Spring Cloud Stream 提供了许多抽象和原语,可以简化消息驱动的微服务应用程序的编写。本节概述了以下内容:
应用模型
Spring Cloud Stream 应用程序由中间件中立的核心组成。应用程序通过在外部代理公开的目标与代码中的输入/输出参数之间建立绑定来与外界进行通信。**建立绑定所需的代理特定细节由特定于中间件的Binder实现处理。
图 1.Spring Cloud Stream 应用程序
Binder 抽象
Spring Cloud Stream 为Kafka和Rabbit MQ提供了 Binder 实现。该框架还包括一个测试绑定器,用于将您的应用程序作为 spring-cloud-stream 应用程序进行集成测试。有关更多详细信息,请参阅测试部分。
Binder 抽象也是该框架的扩展点之一,这意味着您可以在 Spring Cloud Stream 之上实现自己的 Binder。在如何从头开始创建 Spring Cloud Stream Binder中,社区成员详细发布了文档,并举例说明了实现自定义 Binder 所需的一组步骤。该部分中还突出显示了这些步骤Implementing Custom Binders
。
Spring Cloud Stream 使用 Spring Boot 进行配置,Binder 抽象使 Spring Cloud Stream 应用程序能够灵活地连接中间件。例如,部署人员可以在运行时动态选择外部目标(例如 Kafka 主题或 RabbitMQ 交换)与消息处理程序的输入和输出(例如函数的输入参数及其返回参数)之间的映射。application.yml
此类配置可以通过外部配置属性并以 Spring Boot 支持的任何形式(包括应用程序参数、环境变量和/或application.properties
文件)提供。在Spring Cloud Stream 简介部分的接收器示例中,将spring.cloud.stream.bindings.input.destination
应用程序属性设置为raw-sensor-data``raw-sensor-data
使其从Kafka 主题或绑定到 RabbitMQ 交换的队列中读取raw-sensor-data
。
Spring Cloud Stream 自动检测并使用在类路径上找到的绑定器。您可以使用相同的代码使用不同类型的中间件。为此,请在构建时包含不同的绑定器。对于更复杂的用例,您还可以将多个活页夹与应用程序打包在一起,并让它在运行时选择活页夹(甚至是否为不同的绑定使用不同的活页夹)。
持久的发布-订阅支持
应用程序之间的通信遵循发布-订阅模型,其中数据通过共享主题广播。下图显示了一组交互的 Spring Cloud Stream 应用程序的典型部署。
图 2. Spring Cloud Stream 发布-订阅
传感器向 HTTP 端点报告的数据被发送到名为 的公共目标raw-sensor-data
。从目的地开始,它由一个计算时间窗口平均值的微服务应用程序和另一个将原始数据提取到 HDFS(Hadoop 分布式文件系统)的微服务应用程序独立处理。为了处理数据,两个应用程序都在运行时将主题声明为它们的输入。
发布-订阅通信模型降低了生产者和消费者的复杂性,并允许将新应用程序添加到拓扑中,而不会中断现有流。例如,在平均值计算应用程序的下游,您可以添加一个计算最高温度值以进行显示和监控的应用程序。然后,您可以添加另一个应用程序来解释相同的平均值流以进行故障检测。通过共享主题而不是点对点队列进行所有通信可以减少微服务之间的耦合。
虽然发布-订阅消息传递的概念并不新鲜,但 Spring Cloud Stream 采取了额外的步骤,使其成为其应用程序模型的固执己见的选择。通过使用原生中间件支持,Spring Cloud Stream 还简化了跨不同平台的发布-订阅模型的使用。
消费者群体
虽然发布-订阅模型可以轻松地通过共享主题连接应用程序,但通过创建给定应用程序的多个实例进行扩展的能力也同样重要。这样做时,应用程序的不同实例被置于竞争的消费者关系中,其中只有一个实例需要处理给定的消息。
Spring Cloud Stream 通过消费者组的概念来模拟这种行为。(Spring Cloud Stream 消费者组与 Kafka 消费者组类似,并且受到 Kafka 消费者组的启发。)每个消费者绑定都可以使用该spring.cloud.stream.bindings.<bindingName>.group
属性来指定组名称。对于下图所示的消费者,该属性将被设置为spring.cloud.stream.bindings.<bindingName>.group=hdfsWrite
或spring.cloud.stream.bindings.<bindingName>.group=average
。
图 3. Spring Cloud Stream 消费者组
订阅给定目标的所有组都会收到已发布数据的副本,但每个组中只有一个成员从该目标接收给定消息。默认情况下,当未指定组时,Spring Cloud Stream 会将应用程序分配给一个匿名且独立的单成员消费者组,该组与所有其他消费者组处于发布-订阅关系。
消费者类型
支持两种类型的消费者:
- 消息驱动(有时称为异步)
- 轮询(有时称为同步)
在 2.0 版本之前,仅支持异步消费者。一旦消息可用并且有线程可以处理它,消息就会被传递。
当您希望控制处理消息的速率时,您可能需要使用同步使用者。
耐用性
与Spring Cloud Stream的应用程序模型一致,消费者组订阅是持久的。也就是说,绑定器实现确保组订阅是持久的,并且一旦创建了一组的至少一个订阅,该组就会接收消息,即使消息是在组中的所有应用程序停止时发送的。
匿名订阅本质上是非持久的。对于某些绑定器实现(例如 RabbitMQ),可能存在非持久组订阅。 | |
---|---|
通常,在将应用程序绑定到给定目标时,最好始终指定消费者组。当扩展 Spring Cloud Stream 应用程序时,您必须为其每个输入绑定指定一个使用者组。这样做可以防止应用程序的实例接收重复的消息(除非需要这种行为,但这是不寻常的)。
分区支持
Spring Cloud Stream 提供对给定应用程序的多个实例之间的数据分区的支持。在分区场景中,物理通信介质(例如代理主题)被视为被构造为多个分区。一个或多个生产者应用程序实例将数据发送到多个消费者应用程序实例,并确保由共同特征标识的数据由同一消费者实例处理。
Spring Cloud Stream 提供了一个通用抽象,用于以统一的方式实现分区处理用例。因此,无论代理本身是否自然分区(例如 Kafka)或不自然分区(例如 RabbitMQ),都可以使用分区。
图 4.Spring Cloud Stream 分区
分区是有状态处理中的一个关键概念,其中确保所有相关数据一起处理(出于性能或一致性原因)至关重要。例如,在时间窗口平均值计算示例中,来自任何给定传感器的所有测量值都由同一应用程序实例处理非常重要。
要建立分区处理场景,您必须同时配置数据生产端和数据消费端。 |
---|