[英]Consume messages from topic and retry with exponential backoff till it succeeds with Spring-Kafka-2.3.0 and above
以下是配置
@Bean
@Autowired
public ConcurrentKafkaListenerContainerFactory<byte[], byte[]> kafkaListContFactory(@Qualifier("retryTemplate") RetryTemplate retryTemplate, @Qualifier("batchErrorHandler") ErrorHandler errorHandler, @Qualifier("batchErrorHandler") BatchErrorHandler batchErrorHandler) {
ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory();
factory.setConsumerFactory(consumerFactory());
factory.getContainerProperties().setAckOnError(false);
factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);
factory.setErrorHandler(errorHandler);
factory.getContainerProperties().setAckOnError(false);
factory.setStatefulRetry(true);
factory.setRetryTemplate(retryTemplate);
}
**Retry config**
@Bean("retryTemplate")
public RetryTemplate retryTemplate() {
final ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(delay);
backOffPolicy.setMultiplier(multiplier);
backOffPolicy.setMaxInterval(20000);
final RetryTemplate template = new RetryTemplate();
template.setRetryPolicy(new AlwaysRetryPolicy());
template.setBackOffPolicy(backOffPolicy);
return template;
}
SeekToCurrentErrorHandler config
I do not want to recover and try to retry till it succeeds so I have given maxAttempts to -1
@Bean("errorHandler")
public ErrorHandler errorHandler() {
final ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
SeekToCurrentErrorHandler handler = new SeekToCurrentErrorHandler((r, t) -> {
if (t != null && (t instanceof RetryServiceException || t.getCause() instanceof RetryServiceException)) {
logger.error("SeekToCurrentErrorHandler recoverer failure", t.getMessage());
throw new RetryServiceException("SeekToCurrentErrorHandler recoverer failure");
}
}, -1);
return handler;
}
最后,当没有异常发生时,我在 @KafkaListener 方法中确认。
我的问题是,如果我将 -1 配置为最大尝试次数并且我的错误处理程序将负责重试,我是否需要 retryTemplate? 但是重试不会无限次发生,问题是如果我获取批处理记录,如果其中一条消息在轮询中失败,我正在处理相同的消息,所有消息都将被重新处理。
我需要使用 batchErrorHandler 并实现指数退避策略,以便重试将是有状态的,并且应该避免重新处理相同的成功消息。 任何人都可以帮助解决上述问题。
我需要避免通过错误使用max.poll.interval.ms来重新平衡分区
您需要使用Stateful Retry来避免重新平衡; 但是,对于现代版本,您根本不需要侦听器级别的重试,因为您现在可以执行重试并在错误处理程序级别退出。
使用构造函数获取BackOff
并删除容器重试模板。
/**
* Construct an instance with the provided recoverer which will be called after
* the backOff returns STOP for a topic/partition/offset.
* @param recoverer the recoverer; if null, the default (logging) recoverer is used.
* @param backOff the {@link BackOff}.
* @since 2.3
*/
public SeekToCurrentErrorHandler(@Nullable BiConsumer<ConsumerRecord<?, ?>, Exception> recoverer, BackOff backOff) {
我需要使用 batchErrorHandler 并实现指数退避策略,以便重试将是有状态的,并且应该避免重新处理相同的成功消息。 任何人都可以帮助解决上述问题。
该框架无法帮助批处理侦听器,因为它不知道(在批处理中)发生故障的位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.