Spring boot SpringBoot microservice@StreamListener在抛出RunTimeException时重试无限时间

Spring boot SpringBoot microservice@StreamListener在抛出RunTimeException时重试无限时间,spring-boot,apache-kafka,spring-cloud-stream,Spring Boot,Apache Kafka,Spring Cloud Stream,我有一个@StreamListener方法,它将在其中执行REST调用。当REST调用返回异常时,@StreamListener方法将抛出RunTimeException并执行重试@StreamListener方法在抛出RuntimeException时将无限次重试 Spring云流重试配置: spring.cloud.stream.kafka.bindings.inputChannel.consumer.enableDlq=true spring.cloud.stream.bindings.i

我有一个@StreamListener方法,它将在其中执行REST调用。当REST调用返回异常时,@StreamListener方法将抛出RunTimeException并执行重试@StreamListener方法在抛出RuntimeException时将无限次重试

Spring云流重试配置:

spring.cloud.stream.kafka.bindings.inputChannel.consumer.enableDlq=true
spring.cloud.stream.bindings.inputChannel.consumer.maxAttempts=3
spring.cloud.stream.bindings.inputChannel.consumer.concurrency=3
spring.cloud.stream.bindings.inputChannel.consumer.backOffInitialInterval=300000
spring.cloud.stream.bindings.inputChannel.consumer.backOffMaxInterval=600000
SpringBoot微服务依赖项版本:

Spring Boot 2.0.3
Spring Cloud Stream Elmhurst.RELEASE
Kafka broker 1.1.0

您当然可以将尝试次数(
maxturets
property)增加到类似于
Integer.MAX\u VALUE
,或者您可以提供自己的
RetryTemplate
bean的实例,该实例可以根据需要进行配置。
这里是您可以获得更多信息的地方

经过几次尝试和错误后,我们发现kafka配置:max.poll.interval.ms默认为5分钟。由于我们的消费者重试机制,对于最坏的情况,我们的整个重试过程将花费15分钟


所以在第一条消息被消费5分钟后,kafka分区决定消费者没有提供任何响应,执行自动平衡并将相同的消息分配给另一个分区。

使用RetryTemplate或增加maxAttempts属性有一个限制,即重试应在
max.poll.interval.ms
内完成,否则Kafka代理将认为消费者已关机,并将分区重新分配给另一个消费者(如果可用)

另一种选择是让听者使用
consumer.seek
方法重新读取来自卡夫卡的相同消息

@StreamListener("events")
public void handleEvent(@Payload String eventString, @Header(KafkaHeaders.CONSUMER) Consumer<?, ?> consumer,
                             @Header(KafkaHeaders.RECEIVED_PARTITION_ID) String partitionId,
                             @Header(KafkaHeaders.RECEIVED_TOPIC) String topic,
                             @Header(KafkaHeaders.OFFSET) String offset) {
   try {
       //do the logic (example: REST call)
   } catch (Exception e) { // Catch only specific exceptions that can be retried
        consumer.seek(new TopicPartition(topic, Integer.parseInt(partitionId)), Long.parseLong(offset));
   }
}
@StreamListener(“事件”)
public void handleEvent(@Payload String eventString,@Header(KafkaHeaders.CONSUMER)使用者使用者使用者,
@标题(KafkaHeaders.RECEIVED_PARTITION_ID)字符串partitionId,
@标题(KafkaHeaders.RECEIVED_主题)字符串主题,
@标题(KafkaHeaders.OFFSET)字符串偏移量){
试一试{
//执行逻辑(例如:REST调用)
}catch(异常e){//仅捕获可重试的特定异常
seek(新的TopicPartition(topic,Integer.parseInt(partitionId)),Long.parseLong(offset));
}
}