26. 主要概念

Spring Cloud Stream 提供了许多抽象和 primitives,简化了 message-driven microservice applications 的编写。本节概述了以下内容:

26.1 Application Model

Spring Cloud Stream application 由 middleware-neutral 核心组成。 application 通过 Spring Cloud Stream 注入其中的输入和输出 channel 与外界通信。 Channels 通过 middleware-specific Binder implementations 连接到外部代理。

图 1_.Spring Cloud Stream Application

SCSt 与 binder

26.1.1 Fat JAR

Spring Cloud Stream applications 可以在 IDE 中以 stand-alone 模式 run 进行测试。要在 production 中运行 Spring Cloud Stream application,您可以使用为 Maven 或 Gradle 提供的标准 Spring Boot 工具创建可执行文件(或“fat”)JAR。有关详细信息,请参阅Spring Boot Reference Guide

26.2 Binder Abstraction

Spring Cloud Stream 为KafkaRabbit MQ提供 Binder implementations。 Spring Cloud Stream 还包含一个TestSupportBinder,它保持 channel 不被修改,以便测试可以直接与 channels 交互并可靠地断言收到的内容。您还可以使用可扩展 API 编写自己的 Binder。

Spring Cloud Stream 使用 Spring Boot 进行 configuration,Binder 抽象使得 Spring Cloud Stream application 可以灵活地连接到中间件。例如,部署人员可以在运行时动态选择 channels 连接的目的地(例如 Kafka 主题或 RabbitMQ 交换)。这种 configuration 可以通过外部 configuration properties 以及 Spring Boot 支持的任何形式提供(包括 application arguments,环境变量和application.ymlapplication.properties files)。在第 25 章,介绍 Spring Cloud Stream部分的 sink example 中,将spring.cloud.stream.bindings.input.destination application property 设置为raw-sensor-data会使其从raw-sensor-data Kafka topic 或绑定到raw-sensor-data RabbitMQ 交换的队列中读取。

Spring Cloud Stream 自动检测并使用 classpath 上的 binder。您可以使用具有相同 code 的不同类型的中间件。为此,请在 build time 中包含不同的 binder。对于更复杂的用例,您还可以使用 application 打包多个 binders,并让它在运行时选择 binder(甚至是否为不同的 channel 使用不同的 binders)。

26.3 持久 Publish-Subscribe 支持

applications 之间的通信遵循 publish-subscribe model,其中数据通过共享主题 broadcast。这可以在下图中看到,该图显示了一组交互 Spring Cloud Stream applications 的典型部署。

图 1_.Spring Cloud Stream Publish-Subscribe

SCSt 传感器

传感器向 HTTP 端点报告的数据将发送到名为raw-sensor-data的 common 目标。从目的地开始,它由一个计算 time-windowed 平均值的微服务应用程序和另一个将原始数据摄入 HDFS(Hadoop 分布式文件系统)的微服务应用程序独立处理。在 order 处理数据时,两个 applications 都在运行时声明 topic 作为它们的输入。

publish-subscribe communication model 降低了 producer 和 consumer 的复杂性,并允许将新的 applications 添加到拓扑中,而不会中断现有流。对于示例,在 average-calculating application 的下游,您可以添加一个 application 来计算显示和监视的最高温度值。然后,您可以添加另一个 application,用于解释相同的平均流量以进行故障检测。通过共享主题而不是 point-to-point 队列进行所有通信可以减少微服务之间的耦合。

虽然 publish-subscribe 消息传递的概念并不新鲜,但 Spring Cloud Stream 采用额外的步骤使其成为其 application model 的自以为是的选择。通过使用本机中间件支持,Spring Cloud Stream 还简化了跨不同平台的 publish-subscribe model 的使用。

26.4 Consumer Groups

虽然 publish-subscribe model 可以通过共享主题轻松连接 applications,但通过创建给定 application 的多个实例来扩展的能力同样重要。这样做时,application 的不同实例被放置在竞争的 consumer 关系中,其中只有一个实例需要处理给定的消息。

Spring Cloud Stream 通过 consumer group 的概念对此行为进行建模。 (Spring Cloud Stream consumer 组与 Kafka consumer 相似并受其启发 groups.)每个 consumer binding 可以使用spring.cloud.stream.bindings.<channelName>.group property 指定 group name。对于下图中显示的使用者,此 property 将设置为spring.cloud.stream.bindings.<channelName>.group=hdfsWritespring.cloud.stream.bindings.<channelName>.group=average

图 1_.Spring Cloud Stream Consumer Groups

SCSt 小组

订阅给定目标的所有组都会收到已发布数据的副本,但每个 group 中只有一个成员从该目标接收给定的消息。默认情况下,如果未指定 group,Spring Cloud Stream 会将 application 分配给与所有其他 consumer 组处于 publish-subscribe 关系的匿名且独立的 single-member consumer group。

26.5 消费者类型

支持两种类型的 consumer:

  • Message-driven(有时称为异步)

  • 轮询(有时称为同步)

在 version 2.0 之前,仅支持异步使用者。消息一旦可用就会传递,并且可以使用一个线程来处理它。

如果希望控制处理消息的速率,可能需要使用同步 consumer。

26.5.1 耐久性

与 Spring Cloud Stream 的固定 application model 一致,consumer group 订阅是持久的。也就是说,binder implementation 确保 group 订阅是持久的,并且一旦创建了 group 的至少一个订阅,group 就会接收消息,即使它们是在 group 中的所有 applications 停止时发送的。

匿名订阅本质上是 non-durable。对于某些 binder implementations(例如 RabbitMQ),可以有 non-durable group 订阅。

通常,在将 application 绑定到给定目标时,最好始终指定 consumer group。放大 Spring Cloud Stream application 时,必须为每个输入绑定指定一个 consumer group。这样做可以防止 application 的实例接收重复的消息(除非需要这种行为,这是不寻常的)。

26.6 分区支持

Spring Cloud Stream 支持在给定 application 的多个实例之间对数据进行分区。在分区方案中,物理通信介质(例如 broker topic)被视为结构化为多个分区。一个或多个 producer application 实例将数据发送到多个 consumer application 实例,并确保 common 特性标识的数据由同一个 consumer 实例处理。

Spring Cloud Stream 提供了一个 common 抽象,用于以统一的方式实现分区处理用例。无论 broker 本身是自然分区(对于 example,Kafka)还是不是(对于 example,RabbitMQ),都可以使用分区。

图 1_.Spring Cloud Stream Partitioning

SCSt 分区

分区是有状态处理中的一个关键概念,其中确保所有相关数据一起处理是至关重要的(出于性能或一致性原因)。例如,在 time-windowed 平均计算 example 中,重要的是来自任何给定传感器的所有测量都由相同的 application 实例处理。

要设置分区处理方案,必须同时配置 data-producing 和 data-consuming ends。