繁体   English   中英

使用来自主题的消息并使用指数退避重试,直到使用 Spring-Kafka-2.3.0 及更高版本成功

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM