Spring-Kafka确认机制报错:No Acknowledgment available as an argument

问题出现

在spring boot集成kafka时报错,报错信息:

java 复制代码
No Acknowledgment available as an argument, the listener container must have a MANUAL AckMode to populate the Acknowledgment.

翻译: Acknowledgment 参数不可用,监听容器需要设置一个手动的 AckMode 才能填充Acknowledgment。

问题代码:

java 复制代码
@KafkaListener(topics = PENDING_TOPIC, groupId = KafkaProducer.TOPIC_GROUP1)
    public void topic_test(ConsumerRecord<?, ?> record, Acknowledgment ack, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
        Optional message = Optional.ofNullable(record.value());
        if (message.isPresent()) {
            Object msg = message.get();
            logger.info("topic.group1 消费了: Topic:" + topic + ",Message:" + msg);
            ack.acknowledge();
        }
    }

这是参考其他人的消费者端的代码,方法里有Acknowledgment 类型参数,说明该参数没有被识别。首先查一下这个参数的含义。

问题分析

Acknowledgment 类型参数的含义:

控制消息的确认机制。在kafka中,消费者提交偏移量时需要确认,执行ack.acknowledge();后代表告诉 Kafka 消费者组,当前的消息已经被成功处理并且可以提交偏移量。这意味着消费者不会再次处理这条消息。

Spring-kafka 提供了多种确认机制,也就是 AckMode。官方文档显示AckMode 有以下几种:

  • RECORD: 当监听器处理完记录返回时,提交偏移量.
  • BATCH: 处理完 poll() 返回的所有记录后,提交偏移量。
  • TIME: 当poll()返回的所有记录都已处理完毕后,只要超过上次提交后的 ackTime,就提交偏移量。
  • COUNT: 当poll()返回的所有记录都已处理完毕后,只要上次提交后已收到 ackCount 记录,就提交偏移量。
  • COUNT_TIME: 与 TIME 和 COUNT 类似,但如果任一条件为真,都会执行提交。
  • MANUAL: 处理完一批数据后,手动调用 Acknowledgment.acknowledge()方法将offest提交至缓存,之后在下一个poll() 之前用BATCH 方式提交。
  • MANUAL_IMMEDIATE: 当监听器调用 Acknowledgment.acknowledge() 方法时,立即提交偏移量。

报错原因:

从上面的集中确认机制中可以看到,只有MANUAL 和MANUAL_IMMEDIATE 用到了Acknowledgment 其他都没有。所以需要把AckMode 配置成这两个其中一个才行,而查看配置文件发现我确实没有配。

解决办法:

在application.yaml 中配置ack-mode: manual_immediate 。

在自定义配置AckMode 的时候,首先需要将enable-auto-commit 设置成false 才行,2.3版本之后默认是false,不过使用的默认机制是BATCH,所以还需要将ack-mode设成manual_immediate 来覆盖默认配置。

yaml 复制代码
spring:
  kafka:
    bootstrap-servers: localhost:9092
    consumer:
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
        # 值的反序列化方式
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      group-id: geo-friend
      enable-auto-commit: false # 设置成手动提交
      auto-commit-interval: 1S
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
    listener:	# 配置监听容器的ackmode
      concurrency: 5
      ack-mode: manual_immediate
      missing-topics-fatal: false

参考资料:

spring-kafka 文档:https://docs.spring.io/spring-kafka/docs/2.8.2/reference/html/#committing-offsets

相关推荐
老板一杯拿铁2 小时前
Java 八股文面试详解:从基础到进阶的全面梳理
java·面试
const_qiu2 小时前
第 2.5 章 2.5.4-2.5.5:JWT 双 Token 与声明式权限守卫
java·人工智能
bug菌2 小时前
一个周末就想把短链服务推到 10 万 QPS,真能靠加 Redis 做到吗?
java·redis·go
撸串-研究生2 小时前
springboot福利院管理系统73979
java·spring boot·后端·福利院管理系统
xixiaoyunya2 小时前
别再写一堆 if-else 了:用策略模式重构你的业务代码
后端
xianyuCcCcCCCcc2 小时前
Ceph 分布式存储:核心架构与集群部署
分布式·ceph·架构
tachibana22 小时前
Go 语言里的 Context 是什么?
开发语言·后端·golang·go·语言
不得了zz3 小时前
04-Spring AI Alibaba ReactAgent 生产级实践:工具调用、结构化输出、HITL 与上下文管理
java·ai编程·springaialibaba
猿究院_夏燊3 小时前
SpringMVC 到底是怎么干活的?
java·网络·职场和发展
鶴哥只手遮天3 小时前
Spring Framework 7.0.9 深度剖析-05-配置元数据解析:XML、注解与 JavaConfig
java·后端·开源