我正在使用spring kafka 2.2.7,我的使用者配置代码如下:
@Slf4j
@Configuration
@EnableKafka
public class KafkaConfiguration {
@Bean
ConcurrentKafkaListenerContainerFactory<String, Customer> kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, Customer> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
// less than number of partition, will do infinite retry
factory.setConcurrency(1);
SeekToCurrentErrorHandler errorHandler =
new SeekToCurrentErrorHandler((record, exception) -> {
LOGGER.info("***in error handler data, {}", record);
}, 1);
factory.setErrorHandler(errorHandler);
return factory;
}
@Bean
public ConsumerFactory<String, Customer> consumerFactory() {
return new DefaultKafkaConsumerFactory<>(consumerConfigs());
}
@Bean
public Map<String, Object> consumerConfigs() {
Map<String, Object> props = new HashMap<>();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ErrorHandlingDeserializer2.class);
props.put(ErrorHandlingDeserializer2.VALUE_DESERIALIZER_CLASS, KafkaAvroDeserializer.class);
props.put("schema.registry.url", "http://127.0.0.1:8081");
props.put("specific.avro.reader", "true");
props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
return props;
}
}
@Component
@Slf4j
public class KafkaConsumerService {
@KafkaListener(id = "demo-consumer-stream-group", topics = "kafka-demo-avro")
public void process(ConsumerRecord<String, Customer> record) {
LOGGER.info("Customer key: {} and value: {}", record.key(), record.value());
LOGGER.info("topic: {}, partition: {}, offset: {}", record.topic(), record.partition(), record.offset());
throw new RuntimeException("force to retry");
}
}
因此,如果我的侦听器中发生异常,即使我在配置中配置的maxFailures小于我主题的分区计数,即使我在配置中配置了maxFailures,使用者也将永远重试失败的消息。
只有在我至少一秒一间隔地发送消息时,它才有效。如果我批量发送该消息,则该行为将不起作用。除非重新启动使用者,否则它将无法正常工作。
复制步骤:
1.创建一个具有多个分区的主题,例如3或6
2.在Spring Kafka配置中,将并发级别指定为1
3.对于SeekToCurrentErrorHandler
,将maxFailure
指定为正值,例如3
4.向主题发送数十条消息
您将看到每条失败的消息将进行无限次重试,而不是我指定的maxFailure
。此外,我可以看到许多消息落后于消费者的滞后。
但是,如果停止侦听器并再次启动侦听器,它将正确跳过失败的消息。
答案 0 :(得分:1)
这是Spring Kafka 2.2.7.RELEASE
的错误,但已在2.2.8.RELEASE
中修复。
答案 1 :(得分:0)
我使用的是2.2.8,我仍然可以重现该错误,但是配置更为复杂。我需要同时将SeekToCurrentEH
和retryTemplate
与ExponentialRandomBackOffPolicy
一起使用。因此,仍然有碰到它的风险。
已报告here。