微服务: springboot整合kafka实现消息的简单收发(上)

全文目录,一步到位

  • 1.前言简介
    • [1.1 专栏传送门](#1.1 专栏传送门)
      • [1.1.1 上文小总结](#1.1.1 上文小总结)
      • [1.1.2 上文传送门](#1.1.2 上文传送门)
  • [2. springboot基础使用](#2. springboot基础使用)
    • [2.1 pom的依赖安装](#2.1 pom的依赖安装)
    • [2.2 yml配置文件](#2.2 yml配置文件)
      • [2.2.1 代码如下](#2.2.1 代码如下)
    • [2.3 java代码如下](#2.3 java代码如下)
      • [2.3.1 创建topic](#2.3.1 创建topic)
      • [2.3.2 创建生产者(`发送消息`)](#2.3.2 创建生产者(发送消息))
      • [2.3.3 创建消费者(`接收消息`)](#2.3.3 创建消费者(接收消息))
      • [2.3.4 执行效果](#2.3.4 执行效果)
      • [2.3.5 定时接收消息(定时消费-手动消费)](#2.3.5 定时接收消息(定时消费-手动消费))
  • [3. 文章的总结与预告](#3. 文章的总结与预告)
    • [3.1 本文总结](#3.1 本文总结)
    • [3.2 下文预告](#3.2 下文预告)

1.前言简介

1.1 专栏传送门

===> 传送门: 分布式必备服务配置

1.1.1 上文小总结

上文主要介绍了如何使用docker安装使用kafka,以及遇到问题如何排查

1.1.2 上文传送门

08 Docker安装kafka与zookeeper, 遇到异常排查方法与springboot如何使用

2. springboot基础使用

Kafka作为高吞吐、低延迟的分布式消息系统,常用于解耦数据生产者和消费者,实现实时数据流处理与日志聚合

2.1 pom的依赖安装

如果使用高版本jdk 请对应更换, 不然会报错的

xml 复制代码
     <!--kafka的版本是2.8.1,使用springboot的-->
        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-clients</artifactId>
            <version>2.8.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
            <version>2.7.9</version>
        </dependency>

2.2 yml配置文件

2.2.1 代码如下

没有安全校验的普通yml 后面会介绍进阶版

yaml 复制代码
spring:
  kafka:
    # 消费者
    consumer:
      group-id: test-consumer
      auto-offset-reset: earliest
      bootstrap-servers: ip:9092
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
    # 生产者(增加超时/重试配置)
    producer:
      bootstrap-servers: ip:9092
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
      retries: 3  # 重试次数
      batch-size: 16384
      buffer-memory: 33554432
      properties:
        linger.ms: 1  # 批量发送延迟
        request.timeout.ms: 30000  # 请求超时(默认30s,可适当调大)
        delivery.timeout.ms: 60000  # 投递超时(默认120s,适配报错的120s超时)

2.3 java代码如下

2.3.1 创建topic

避免自动创建的topic没有leader

java 复制代码
import org.apache.kafka.clients.admin.NewTopic;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.config.TopicBuilder;

@Configuration
public class KafkaTopicConfig {
    @Bean
    public NewTopic testTopic() {
        // 分区数与分区数
        return TopicBuilder.name("pzy1")
                .partitions(1)
                .replicas(1)
                .build();
    }
}

2.3.2 创建生产者(发送消息)

写个controller 增加成功与失败回调

java 复制代码
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@AllArgsConstructor
public class KafkaSimpleController {

    private final KafkaTemplate<Object, Object> kafkaTemplate;

    @GetMapping("/send/{messge}")
    public String send(@PathVariable String messge) {
        kafkaTemplate.send("test", "topci1:" + messge)
                .addCallback(result -> {
                    // 发送成功处理
                    log.info("===> 消息发送成功: {}",result);

                }, failure -> {
                    // 发送失败处理
                    log.error("===> 消息发送失败: {}",failure.getMessage());
                });
        kafkaTemplate.send("test", "topci2:" + messge);
        return messge;
    }
}

2.3.3 创建消费者(接收消息)

java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class SimpleListener {

    @Autowired
    private StringRedisTemplate  redisTemplate;


    @KafkaListener(topics = {"test"},groupId = "test-consumer")
    public void listen1(String data) {
        log.info("===> topic:test的消费者消息成功 , 消息是: {}",data);

        redisTemplate.opsForValue().set("kafka:test", data);
    }


}

2.3.4 执行效果

篇幅太长了, 拆开吧, 先存几张图片

2.3.5 定时接收消息(定时消费-手动消费)

看到其他人代码的写法 我记录一下哈 (业务需求 改手动拉取消费)

java 复制代码
@Component
@EnableScheduling
@Slf4j
public class TimedKafkaConsumer {

    @Autowired
    private StringRedisTemplate redisTemplate;

    // 注入Spring管理的ConsumerFactory(替代直接注入KafkaConsumer)
    @Autowired
    private ConsumerFactory<String, String> consumerFactory;

    // Redis List的Key(按Topic命名,便于管理)
    private static final String REDIS_LIST_KEY = "kafka:msg:test";

    // 声明KafkaConsumer,后续通过ConsumerFactory创建
    private KafkaConsumer<String, String> kafkaConsumer;

    // 订阅的Topic(改成你实际的Topic,比如之前的"test")
    private static final String TOPIC = "test";

    // 可选:Redis key过期时间(单位秒,避免数据堆积,比如7天)
    private static final long REDIS_KEY_EXPIRE_SECONDS = 60 * 60 * 24 * 7L;

    @PostConstruct
    public void init() {
        // 通过ConsumerFactory创建KafkaConsumer实例(Spring会自动填充配置)
        kafkaConsumer = (KafkaConsumer<String, String>) consumerFactory.createConsumer();
        // 订阅Topic
        kafkaConsumer.subscribe(Collections.singletonList(TOPIC));
    }

    // 核心:每5秒执行一次消费(fixedRate=5000)
    @Scheduled(fixedRate = 5000, initialDelay = 1000)
    public void consume() {
        try {
            // 拉取消息(超时时间设为1秒,避免阻塞)
            ConsumerRecords<String, String> records = kafkaConsumer.poll(Duration.ofMillis(1000));
            if (records.isEmpty()) {
                log.info("本次拉取无消息,5秒后重试");
                return;
            }
            int msgCount = 0;
            // 处理消息
            for (ConsumerRecord<String, String> record : records) {
//                System.out.printf("消费消息:offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
//                // 业务逻辑处理...

                msgCount++;
                // 1. 格式化消息内容(包含offset/key/value,便于后续解析)
                String msgContent = String.format(
                        "offset=%d,key=%s,value=%s,topic=%s,timestamp=%d",
                        record.offset(),
                        record.key() == null ? "null" : record.key(),
                        record.value() == null ? "null" : record.value(),
                        record.topic(),
                        record.timestamp()
                );

                // 2. 核心:追加消息到Redis List(右追加,保证时序)
                redisTemplate.opsForList().rightPush(REDIS_LIST_KEY, msgContent);

                // 打印日志(替代System.out)
                log.info("消费并存储消息:{}", msgContent);

            }

            // 手动提交偏移量(需确保配置中enable-auto-commit=false)
            kafkaConsumer.commitSync();
            log.info("本次消费{}条消息,已全部追加到Redis List", msgCount);
        } catch (Exception e) {
            log.error("消费/存储消息异常", e);
            e.printStackTrace();
            // 异常处理(如重试、告警)
        }
    }

    @PreDestroy
    public void close() {
        // 关闭消费者
        if (kafkaConsumer != null) {
            kafkaConsumer.close();
        }
    }
}

3. 文章的总结与预告

3.1 本文总结

简单的实现kafka的基础操作, 请先完成上篇文章后使用

3.2 下文预告

===> 传送门: kafka sasl认证 <==+


@author: pingzhuyan
@description: ok
@year: 2024

相关推荐
Gavin在路上2 小时前
dubbo源码之微服务治理的“隐形遥控器”——QOS 机制解析
微服务·架构·dubbo
嘻哈baby3 小时前
Nacos服务注册与配置中心实战指南
微服务
sszdlbw3 小时前
后端springboot框架入门学习--第二篇
java·spring boot·学习
阿拉斯攀登3 小时前
MyBatis 全面解析 & Spring Boot 集成实战
java·spring boot·mybatis·持久层框架
qq_12498707533 小时前
基于springboot健康养老APP的设计与实现(源码+论文+部署+安装)
java·spring boot·后端·mysql·微信小程序·毕业设计
2501_924064114 小时前
2025年优测全链路压测平台:高并发卡顿环节精准定位实践
微服务·压测方案
赵榕4 小时前
RabbitMQ发布订阅模式同一消费者多个实例如何防止重复消费?
分布式·微服务·rabbitmq
lang201509284 小时前
Kafka高可用:延迟请求处理揭秘
分布式·kafka·linq
Selegant5 小时前
告别传统部署:用 GraalVM Native Image 构建秒级启动的 Java 微服务
java·开发语言·微服务·云原生·架构