SpringBoot 接入 Kafka 完整实操步骤

SpringBoot 接入 Kafka 完整实操步骤

一、前置环境准备

  1. 启动 Kafka 服务 (本地测试,KRaft 或 Zookeeper 模式均可,默认端口 9092

    • 本地快速测试可用 docker-compose 拉起单节点 Kafka
    • 确认 server.propertiesadvertised.listeners=PLAINTEXT://localhost:9092,外网访问改为对应公网 IP
  2. 提前确认 Topic(可以代码自动创建,也可以命令行手动创建)

    手动创建topic示例

    bin/kafka-topics.sh --create --topic demo-topic --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1

二、引入 Maven 依赖

SpringBoot2.x:推荐 spring-boot-starter-kafka;SpringBoot3.x 直接使用 spring-kafka(starter 已移除),不用写版本,父工程自动管理兼容版本

复制代码
<!-- SpringBoot 2.x -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-kafka</artifactId>
</dependency>

<!-- SpringBoot 3.x -->
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>

<!-- 可选:web用于测试接口 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

三、配置文件 application.yml(核心)

基础最简配置(字符串收发,开发调试)

复制代码
spring:
  kafka:
    # kafka集群地址,多个用逗号分隔
    bootstrap-servers: localhost:9092
    # 生产者配置
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
      acks: 1 # 调试用;生产重要业务改为 all
      retries: 3
    # 消费者配置
    consumer:
      group-id: demo-consumer-group # 消费者组,必须配置
      auto-offset-reset: earliest # 新组没有offset时,从头消费
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      enable-auto-commit: true # 调试自动提交;生产建议关闭手动提交
    listener:
      concurrency: 3 # 消费并发线程,建议 ≤ topic分区数

✅ 生产推荐可靠配置(关闭自动提交、JSON 序列化)

复制代码
spring:
  kafka:
    bootstrap-servers: localhost:9092
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
      acks: all
      retries: 3
      enable-idempotence: true # 幂等生产者,防重复发送
    consumer:
      group-id: demo-consumer-group
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
      enable-auto-commit: false # 关闭自动提交,业务成功后手动ack
      max-poll-records: 50
      properties:
        spring.json.trusted.packages: "*" # JSON反序列化信任所有包
    listener:
      ack-mode: MANUAL_IMMEDIATE # 手动立即提交offset
      concurrency: 3

四、代码实现

1. 生产者(发送消息,KafkaTemplate)

SpringBoot 自动注入 KafkaTemplate,直接 Autowired 使用

复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class KafkaProducerController {

    @Autowired
    private KafkaTemplate<String, Object> kafkaTemplate;

    private static final String TOPIC_NAME = "demo-topic";

    // 异步发送(推荐,非阻塞)
    @GetMapping("/send")
    public String sendMsg(@RequestParam String msg) {
        kafkaTemplate.send(TOPIC_NAME, msg).addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
            @Override
            public void onSuccess(SendResult<String, Object> result) {
                System.out.println("发送成功:offset=" + result.getRecordMetadata().offset());
            }
            @Override
            public void onFailure(Throwable ex) {
                System.err.println("发送失败:" + ex.getMessage());
            }
        });
        return "发送完成:" + msg;
    }

    // 同步发送(阻塞,适合强一致性场景)
    /*
    public void syncSend(String msg) throws ExecutionException, InterruptedException {
        SendResult<String, Object> sendResult = kafkaTemplate.send(TOPIC_NAME, msg).get();
    }
    */
}

2. 消费者(@KafkaListener 监听消息)

方式 1:基础消费(自动提交,调试)
复制代码
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;

@Component
public class KafkaConsumer {

    @KafkaListener(topics = "demo-topic", groupId = "demo-consumer-group")
    public void consume(ConsumerRecord<String, Object> record) {
        System.out.printf("收到消息:topic=%s, partition=%d, offset=%d, message=%s%n",
                record.topic(), record.partition(), record.offset(), record.value());
    }
}
方式 2:手动提交 offset(生产推荐,保证业务成功再提交)
复制代码
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Component;

@Component
public class KafkaManualConsumer {

    @KafkaListener(topics = "demo-topic", groupId = "demo-consumer-group")
    public void consume(ConsumerRecord<String, Object> record, Acknowledgment ack) {
        try {
            // 执行业务逻辑
            System.out.println("业务处理消息:" + record.value());
            // 业务成功,手动提交offset
            ack.acknowledge();
        } catch (Exception e) {
            // 业务异常:不提交offset,下次重启重新消费;可搭配重试/死信队列
            e.printStackTrace();
        }
    }
}

3. 【可选】代码自动创建 Topic(项目启动不存在则创建)

复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.config.TopicBuilder;
import org.springframework.kafka.core.NewTopic;

@Configuration
public class KafkaTopicConfig {

    @Bean
    public NewTopic demoTopic() {
        // topic名称、分区数、副本数
        return TopicBuilder.name("demo-topic")
                .partitions(3)
                .replicas(1)
                .build();
    }
}

五、测试流程

  1. 启动 SpringBoot 应用
  2. 浏览器访问接口:http://localhost:8080/send?msg=hello-kafka
  3. 查看控制台消费者打印消息,验证收发正常

六、进阶常用方案

  1. 批量消费 :容器工厂开启 setBatchListener(true),监听方法接收 List<ConsumerRecord>
  2. 消息重试 + 死信队列 :Spring-Kafka 提供 @RetryableTopic + @DltHandler 注解,异常消息重试耗尽转入 DLT 死信主题CSDN博...
  3. 对象序列化 :使用 JsonSerializer / JsonDeserializer,注意信任包配置
  4. 事务消息:生产者开启事务,实现「数据库操作 + 发消息」原子一致性
  5. 幂等消费:Kafka 至少一次投递,业务层必须做幂等(唯一 key 去重)

七、常见踩坑

  1. 连接超时bootstrap-servers 地址错误、防火墙 9092 端口未开放、advertised.listeners 配置内网地址外部无法访问
  2. 序列化异常 :生产者和消费者序列化器不一致;JSON 序列化未配置 spring.json.trusted.packages
  3. 重复消费:业务处理成功后应用崩溃,offset 未提交 → 关闭自动提交 + 业务幂等
  4. 消费阻塞积压concurrency 并发数大于分区数无效;业务处理耗时过长超过 max.poll.interval.ms 触发 rebalance
  5. 同一消费者组多实例负载均衡:分区数量决定最大并行消费能力,实例超过分区数会空闲

八、版本兼容提醒

  • SpringBoot 2.7.x → spring-kafka 2.9.x
  • SpringBoot 3.0.x → spring-kafka 3.0.x
  • SpringBoot 3.1.x → spring-kafka 3.1.x
  • SpringBoot 3.2.x → spring-kafka 3.2.x
相关推荐
深漂的华哥1 小时前
Ruoyi-Vue-Plus(V5.6.2) 开发环境搭建
java·前端·spring boot·后端·spring·ruoyi
斯内普吖1 小时前
(开源)农产品电商系统实战指南 基于 Java + SpringBoot + Vue + MySQL
java·vue.js·spring boot·mysql·开源
Sayai1 小时前
Kafka 集群开启 SASL 认证实战(二):外置 ZooKeeper 之 kafka 与 zk 间认证
分布式·zookeeper·kafka
Sayai1 小时前
Kafka 集群开启 SASL 认证实战(一):内置 ZooKeeper 场景,JAAS 配置全流程
分布式·zookeeper·kafka
Sayai1 小时前
Kafka 集群开启 SASL 认证实战(三):外置 ZooKeeper 完整版,quorum 认证 + ACL 访问控制
zookeeper·kafka·linq
海兰1 小时前
【Kafka进阶6】顺序消费深度解析
分布式·kafka·linq
智码看视界2 小时前
Day58-K8s部署Spring Boot微服务:ConfigMap+Secret+HPA
spring boot·微服务·云原生·kubernetes·k8s·hpa
2601_960906722 小时前
Anthropic把Claude Code 2.1.236及以上版本的Fable 5会话
人工智能·kafka·时序数据库·etcd·tdengine
深漂的华哥12 小时前
Ruoyi-Plus前后端分离场景下,数据加密传输
java·spring boot·后端·开源·maven·ruoyi