我的容器工厂有一个SeekToCurrentErrorHandler,它使用DeadLetterPublishingRecoverer将某些“ NotRetryableException”类型的异常发布到DLT,并为其他种类的异常无限次地寻找相同的偏移量。通过此设置,在一定数量的有效负载导致不可重试的异常之后,存储重试上下文的映射-MapRetryContextCache(spring-retry)溢出,并抛出RetryCacheCapacityExceededException。从最初的外观看,不会从MapRetryContextCache中删除将由DLT恢复器处理的消息的重试上下文。要么是我的配置不正确。
SeekToCurrentErrorHandler eh = new SeekToCurrentErrorHandler(
new DeadLetterPublishingRecoverer(kafkaTemplate),-1);
eh.addNotRetryableException(SomeNonRetryableException.class);
eh.setCommitRecovered(true);
ConcurrentKafkaListenerContainerFactory<String, String> factory
= getContainerFactory();
factory.setErrorHandler(eh);
factory.setRetryTemplate(retryTemplate);
factory.setStatefulRetry(true);
答案 0 :(得分:0)
为了清除缓存,必须在重试模板中而不是在错误处理程序中进行恢复。
@SpringBootApplication
public class So56846940Application {
public static void main(String[] args) {
SpringApplication.run(So56846940Application.class, args);
}
@Bean
public NewTopic topic() {
return TopicBuilder.name("so56846940").partitions(1).replicas(1).build();
}
@Bean
public NewTopic topicDLT() {
return TopicBuilder.name("so56846940.DLT").partitions(1).replicas(1).build();
}
@Bean
public ApplicationRunner runner(KafkaTemplate<String, String> template,
ConcurrentKafkaListenerContainerFactory<String, String> factory,
DeadLetterPublishingRecoverer recoverer) {
factory.setRetryTemplate(new RetryTemplate());
factory.setStatefulRetry(true);
factory.setRecoveryCallback(context -> {
recoverer.accept((ConsumerRecord<?, ?>) context.getAttribute("record"),
(Exception) context.getLastThrowable());
return null;
});
return args -> IntStream.range(0, 5000).forEach(i -> template.send("so56846940", "foo"));
}
@KafkaListener(id = "so56846940", topics = "so56846940")
public void listen(String in) {
System.out.println(in);
throw new RuntimeException();
}
@Bean
public DeadLetterPublishingRecoverer recoverer(KafkaTemplate<String, String> template) {
return new DeadLetterPublishingRecoverer(template);
}
@Bean
public SeekToCurrentErrorHandler eh() {
return new SeekToCurrentErrorHandler(4);
}
}
错误处理程序必须重试至少与重试模板一样多次,以使重试用尽并清除缓存。
还应该为RetryTemplate配置与错误处理程序相同的不可重试的异常。
我们将在参考手册中进行说明。