bigywater.tech
Spring · 130

Spring Cloud Stream:绑定器与消费组

Spring Cloud Stream 的绑定名怎么来的?不配 group 会怎样?新消费组从哪里开始读?处理失败的消息去哪了?为什么我写了两个 Consumer 一条消息都收不到?这篇接一个真实的 Kafka 在 Spring Cloud Stream 5.0.3 上逐项验证。

8 与 8
不配 group 时两个实例各收到全部 8 条消息;配 group 后各收 4 条
3 次后丢弃
消费时抛异常,默认重试 3 次,之后消息被丢掉且重启也不会再收到
一个都不绑
两个函数 bean 且没写 spring.cloud.function.definition 时,应用启动但谁也没有被绑定

绑定名与 topic

实测 · 本机执行输出
  Kafka 里新出现的 topic:['__consumer_offsets', 'in-in-0']
  消费组列表:['anonymous.258622ca-b725-4db5-a927-76e9da123814']
  往 in-in-0 发 m1:['a in 收到 m1 (分区 0)']
  发 m1 之后的消费组:['anonymous.258622ca-b725-4db5-a927-76e9da123814']

in-in-0,topic 自动创建,不配 group 是匿名消费组。

消费组

实测 · 本机执行输出
  [没有 group] 两个实例,同一个 topic:a1 收到 8 条,a2 收到 8 条;消费组 = ['anonymous.…258622ca-b725-4db5-a927-76e9da123814', 'anonymous.…da77a8d2-4701-4c
  [group=g1] 两个实例:b1 收到 4 条(分区 ['0']),b2 收到 4 条(分区 ['1']),合计 8 条

匿名组每个实例收全量;具名组分摊分区。

起始位置

实测 · 本机执行输出
  具名消费组 newgroup 第一次启动:['e1 (分区 0)', 'e2 (分区 0)', 'e3 (分区 0)']
  匿名(没有 group)启动:没有收到任何历史消息

新的具名组从最早开始;匿名组只读新消息。

失败处理

实测 · 本机执行输出
  默认配置:bad-1 的处理日志:['处理 bad-1 抛异常(第 1 次)', '处理 bad-1 抛异常(第 2 次)', '处理 bad-1 抛异常(第 3 次)'];ok-2 是否收到:True
  重启后同一个消费组再启动,是否又收到 bad-1:False
  enableDlq=true:bad-9 被处理了 3 次;Kafka 里的 topic 有 ['error.t-dlq.gdlq', 't-dlq']
  DLQ topic 里的内容:['bad-9']

重试 3 次后丢弃;enableDlq 转存死信 topic。

多个函数

实测 · 本机执行输出
  新出现的 topic:[]
  发到 in-in-0 与 other-in-0 各一条之后收到:[]
  配了 spring.cloud.function.definition=in;other:['in 收到 y1 (分区 0)', 'other 收到 y2 (分区 0)']

必须写 spring.cloud.function.definition。

分步演示

Cloud Stream
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动。Kafka 4.3.1(Homebrew)单节点 KRaft,自己起的实例,端口 9580;往 topic 发消息用 kafka-console-producer;启动失败重试次数与回退没有调整;每个场景之间重启应用
    • 没有验证:RabbitMQ 绑定器;startOffset、resetOffsets 配置;分区生产者(partitionKeyExpression)与 partitionCount;消费者 concurrency;重试次数与回退(maxAttempts / backOffInitialInterval)的修改;死信消息头里携带的原因信息;批量消费(batch-mode);Supplier / Function 的输出绑定;事务;Spring Cloud Stream 与 Spring Kafka 原生监听的区别(见第 140 篇)
    京ICP备2026067502号-1京公网安备11010502063487号