Springboot整合kafka(MQ)

概念

  • 一个topic主题下面有多个分区(比如partition1、partition2、partition3),每个分区有多个副本;从所有的副本中选取一个作为Leader,其他作为Follower,Leader副本 负责消息的接收和消息的消费,Follower只负责数据的同步;当Leader分区故障后,从Follower中选取一个作为新的Leader

  • 一个分区partition只能被消费者组中的一个消费者实例消费,当topic中分区数量发生变化 或者 消费者组中的消费者发生变化 会触发rebalance,重新分配分区partition和消费者实例 之间的关系

  • 生产者发送的消息只在一个partition分区内有序,如果topic下面有多个分区,那所有消息整体是无序的

  • 一个topic可以有多个消费者组,kafka会记录每个"消费者组" 消费到 "哪个分区的哪个偏移量offset"了

下载

  • 下载地址:kafka.apache.org/community/d...

  • /root/kafka/kafka_2.12-3.6.2目录下创建文件夹mq_logs,并在mq_logs文件夹下分别创建文件夹kafka_data_logszookeeper_data分别保存kafka的日志数据和zookeeper的数据

  • mq_logs目录下创建kafka_console.outzookeeper_console.out保存启动程序时的日志输出

  • 进入config目录修改zookeeper.properties,将dataDir改为:dataDir=/root/kafka/kafka_2.12-3.6.2/mq_logs/zookeeper_data

  • 进入config目录修改server.properties

    • 将log.dir改为log.dirs=/root/kafka/kafka_2.12-3.6.2/mq_logs/kafka_data_logs

    • 添加配置:listeners=PLAINTEXT://0.0.0.0:9092 advertised.listeners=PLAINTEXT://localhost:9092

启动

  • 先启动zookeeper:nohup bin/zookeeper-server-start.sh config/zookeeper.properties > /root/kafka/kafka_2.12-3.6.2/mq_logs/zookeeper_console.out 2>&1 &

  • 再启动kafka:nohup bin/kafka-server-start.sh config/server.properties > /root/kafka/kafka_2.12-3.6.2/mq_logs/kafka_console.out 2>&1 &

命令

  • 创建主题:./kafka-topics.sh --create --topic 主题名称 --bootstrap-server localhost:9092

  • 查看所有主题:./kafka-topics.sh --list --bootstrap-server localhost:9092

  • 查看某个主题:./kafka-topics.sh --describe --topic 主题名称 --bootstrap-server localhost:9092

  • 删除某个主题:./kafka-topics.sh --delete --topic 主题名称 --bootstrap-server localhost:9092

  • 查看某个组的消费情况:./kafka-consumer-groups.sh --describe --group 消费者组名称 --bootstrap-server localhost:9092

  • 查看某个组下面的消费者:./kafka-consumer-groups.sh --describe --group 消费组名称 --bootstrap-server localhost:9092 --members

springboot整合kafka

  • 引入依赖

    java 复制代码
    <dependency>
        <groupId>org.springframework.kafka</groupId>
        <artifactId>spring-kafka</artifactId>
    </dependency>
  • 引入配置

    properties 复制代码
    spring.kafka.bootstrap-servers=115.190.156.159:9092
    spring.kafka.producer.retries=3
    spring.kafka.producer.batch-size=1000
    spring.kafka.producer.buffer-memory=33554432
    
    spring.kafka.consumer.group-id=crm-microservice-newperformance
    spring.kafka.consumer.enable-auto-commit=false
    spring.kafka.consumer.auto-offset-reset=earliest
    spring.kafka.consumer.max-poll-records=200
    spring.kafka.listener.ack-mode=MANUAL_IMMEDIATE
  • 配置类:如果程序异常,spring默认将这条消息重复处理9次;这里配置的是同一消息 多次消费失败 的处理策略,即转发到另一个死信topic中;注意,这里是springboot2.7及以上版本的配置方式,和2.7以下版本配置方法不同

    java 复制代码
    @Component
    public class KafkaConfig {
        @Bean
        public CommonErrorHandler errorHandler(KafkaTemplate<Object, Object> template) {
            // 1. 定义死信恢复器,当重试耗尽后,将消息转发到 "原Topic.DLT"
            DeadLetterPublishingRecoverer recover = new DeadLetterPublishingRecoverer(template);
            
            // 2. 定义错误处理器
            DefaultErrorHandler errorHandler = new DefaultErrorHandler(recover, new FixedBackOff(1000L, 3));
    
            return errorHandler;
        }
    }
  • 生产者

    java 复制代码
    @CrossOrigin
    @RestController
    @RequestMapping("/kafka")
    public class KafkaController {
        @Autowired
        private KafkaTemplate<String, String> kafkaTemplate;
    
        @RequestMapping("/send")
        public String send() throws InterruptedException, ExecutionException {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("userid", 1001);
            map.put("name", "ccb"+ UUID.randomUUID());
    
            ListenableFuture<SendResult<String, String>> result = kafkaTemplate.send("test_ccb", JSONObject.toJSONString(map));
            System.out.println("发送结果:"+result.get());
            return "ok";
        }
    }
  • 消费者

    java 复制代码
    public class KafkaConsumer {
    
        // 这里的concurrency=5代表会创建5个消费者实例
        @KafkaListener(topics = {"test_ccb"},concurrency = "5")
        public void consumer(ConsumerRecord<?, ?> consumerRecord, Acknowledgment ack) {
            System.out.println("收到消息:" + consumerRecord);
            ack.acknowledge();
        }
    }

Spring-Kafka原理

  • spring-kafka的自动配置类中,通过KafkaListenerAnnotationBeanPostProcessor 扫描每个Bean对象是否带有@KafkaListener注解,如果有则提取注解上的topicsgroupIdconcurrency等信息封装成一个Endpoint对象,根据Endpoint指定的容器工厂containerFactory创建容器,在容器内运行KafkaConsumer
  • 容器工厂是ConcurrentKafkaListenerContainerFactory,它生产容器KafkaMessageListenerContainer,在容器内运行KafkaConsumer,如果concurrency设置为3,将创建3个容器,也就是会有3个消费者实例
  • 如果程序处理过程中出现了错误,会调用配置好的 CommonErrorHandler进行处理,默认会重试9次,如果还是失败,则提交该偏移量避免阻塞后续消息
  • gemini3剖析过程:gemini.google.com/share/4de80...

相关文章

相关推荐
晚风吹长发7 小时前
初步了解Linux中的动静态库及其制作和使用
linux·运维·服务器·数据结构·c++·后端·算法
梁下轻语的秋缘8 小时前
ESP32-WROOM-32E存储全解析:RAM/Flash/SD卡读写与速度对比
java·后端·spring
wanzhong23338 小时前
开发日记8-优化接口使其更规范
java·后端·springboot
羊小猪~~9 小时前
【QT】--文件操作
前端·数据库·c++·后端·qt·qt6.3
张彦峰ZYF10 小时前
商品供给域的工程化简要设计考量
后端·系统架构·商品模型·商品供给
小北方城市网11 小时前
微服务注册中心与配置中心实战(Nacos 版):实现服务治理与配置统一
人工智能·后端·安全·职场和发展·wpf·restful
爬山算法12 小时前
Hibernate(47)Hibernate的会话范围(Scope)如何控制?
java·后端·hibernate
源码宝13 小时前
云HIS二次开发实施路径指南
后端·源码·二次开发·saas·云his·医院信息系统
李慕婉学姐16 小时前
Springboot旅游景点管理系统2fj40iq6(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
蓝眸少年CY16 小时前
(第八篇)spring cloud之zuul路由网关
后端·spring·spring cloud