一、问题现象

在 Spring Boot 项目中使用 Kafka 批量消费,配置如下:

spring:
  kafka:
    listener:
      type: batch
      ack-mode: manual_immediate
    consumer:
      enable-auto-commit: false

消费者代码:

@KafkaListener(topics = "sms-topic", containerFactory = "batchFactory")
public void consumeBatch(List<<ConsumerRecord<String, String>> records, Acknowledgment ack) {
    // 业务处理...
    ack.acknowledge();
}

启动后报错:

java.lang.IllegalStateException: No Acknowledgment available as an argument, 
the listener container must have a MANUAL AckMode to populate the Acknowledgment.

明明已经在 application.yml 里配置了 ack-mode: manual_immediate,为什么还报这个错?


二、错误堆栈分析

从堆栈可以看到关键调用链:

  1. MessagingMessageListenerAdapter.invokeHandler() 尝试调用消费者方法

  2. checkAckArg() 检查方法参数中是否有 Acknowledgment

  3. 发现容器没有启用 MANUAL AckMode,直接抛异常

核心矛盾: 配置写了手动确认,但运行时容器认为自己是自动确认模式。


三、根本原因

application.yml 中的 spring.kafka.listener.ack-mode 只作用于 Spring Boot 自动配置的默认容器工厂(kafkaListenerContainerFactory)。

当你显式指定了自定义工厂:

@KafkaListener(..., containerFactory = "batchFactory")

Spring 会使用你代码里定义的 batchFactory Bean,而这个自定义工厂完全独立于 YAML 配置,它不会自动读取 application.yml 中的 ack-modeconcurrencylistener 层级的属性。

换句话说:

  • application.yml → 管的是 默认工厂

  • @KafkaListener(containerFactory = "...") → 用的是 自定义工厂

  • 两者是割裂的,自定义工厂的属性必须在 Java Config 里显式编码。

四、解决方案

找到定义 batchFactory 的配置类,手动设置 AckMode

@Configuration
public class KafkaConfig {

    @Bean("batchFactory")
    public ConcurrentKafkaListenerContainerFactory<String, String> batchFactory(
            ConsumerFactory<String, String> consumerFactory) {
        
        ConcurrentKafkaListenerContainerFactory<String, String> factory = 
            new ConcurrentKafkaListenerContainerFactory<>();
        
        factory.setConsumerFactory(consumerFactory);
        factory.setBatchListener(true);
        
        // 关键:显式设置手动立即确认
        factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);
        
        factory.setConcurrency(3);
        return factory;
    }
}

注意: factory.setAckMode()factory.getContainerProperties().setAckMode() 都可以,但推荐后者,因为前者在较新版本中可能被标记为过时。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐