KafkaListenerContainerFactory无法正确创建

时间:2020-03-20 18:11:56

标签: spring-kafka

我有两个侦听器容器工厂,一个用于主主题,另一个用于重试主题,如下所示

@Bean
public ConcurrentKafkaListenerContainerFactory<String, Object> primaryKafkaListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<String, Object> factory = new ConcurrentKafkaListenerContainerFactory<>();
    factory.setConsumerFactory(primaryConsumerFactory());
    factory.setConcurrency(3);
    factory.setAutoStartup(false);
    factory.getContainerProperties().setAckOnError(false);
    factory.getContainerProperties().setAckMode(AckMode.RECORD);        
    errorHandler.setAckAfterHandle(true);
    factory.setErrorHandler(errorHandler);
    return factory;
}

@Bean
public ConsumerFactory<String, Object> primaryConsumerFactory() {
    Map<String, Object> map = new HashMap<>();
    Properties consumerProperties = getConsumerProperties();
    consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, "groupid");
    consumerProperties.forEach((key, value) -> map.put((String) key, value));
    ErrorHandlingDeserializer2<Object> errorHandlingDeserializer = new ErrorHandlingDeserializer2<>(
            getSoapMessageConverter());
    DefaultKafkaConsumerFactory<String, Object> consumerFactory = new DefaultKafkaConsumerFactory<>(map);
    consumerFactory.setValueDeserializer(errorHandlingDeserializer);
    return consumerFactory;
}

@Bean
public ConcurrentKafkaListenerContainerFactory<String, Object> kafkaRetryListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<String, Object> factory = new ConcurrentKafkaListenerContainerFactory<>();
    factory.setConsumerFactory(retryConsumerFactory());
    factory.setConcurrency(3);
    factory.setAutoStartup(false);
    factory.getContainerProperties().setAckOnError(false);
    factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);
    factory.setErrorHandler(new SeekToCurrentErrorHandler(
            new MyDeadLetterPublishingRecoverer("mytopic",
                    deadLetterKafkaTemplate()),
            new FixedBackOff(5000, 2)));
    return factory;
}


@Bean
public ConsumerFactory<String, Object> retryConsumerFactory() {
    Map<String, Object> map = new HashMap<>();
    Properties consumerProperties = getConsumerProperties();
    consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, "retry.id");
    consumerProperties.put("max.poll.interval.ms", "60000");
    consumerProperties.forEach((key, value) -> map.put((String) key, value));
    DefaultKafkaConsumerFactory<String, Object> retryConsumerFactory = new DefaultKafkaConsumerFactory<>(map);
    retryConsumerFactory.setValueDeserializer(getCustomMessageConverter());
    return retryConsumerFactory;
}

我有两个单独的侦听器类,它们使用上述每个容器

这里有两个问题

  1. Spring抱怨-创建名称为'kafkaListenerContainerFactory'的bean时出错,导致原因:org.springframework.beans.factory.NoSuchBeanDefinitionException:没有类型为'org.springframework.kafka.core.ConsumerFactory'的合格bean:至少可以预期1个符合自动装配候选条件的bean。

要解决此问题,我必须将primaryKafkaListenerContainerFactory重命名为kafkaListenerContainerFactory。为什么会这样?

  1. 第二个问题是kafkaRetryListenerContainerFactory似乎没有采用我尝试在retryConsumerFactory中设置的任何属性。(特别是“ max.poll.interval.ms”),而是使用了在kafkaListenerContainerFactory中的primaryConsumerFactory上设置的属性

1 个答案:

答案 0 :(得分:0)

要解决此问题,我必须将primaryKafkaListenerContainerFactory重命名为kafkaListenerContainerFactory。为什么会这样?

那是正确的,当侦听器上没有kafkaListenerContainerFactory时,containerProperty是默认名称,Boot会尝试自动配置它。

您应该使用该名称命名自定义工厂之一,以覆盖Boot的自动配置,因为您的消费工厂不兼容。

您的第二个问题对我来说毫无意义。

也许您的getConsumerProperties()每次都返回相同的对象-您需要一个副本。

在问这样的问题时,最好显示所有相关代码。