【问题标题】:Retry max 3 times when consuming batches in Spring Cloud Stream Kafka Binder在 Spring Cloud Stream Kafka Binder 中消费批次时重试最多 3 次
【发布时间】:2021-09-15 02:57:21
【问题描述】:

我在 kafka 中使用批处理,在带有批处理模式的 spring cloud stream kafka binder 中不支持重试,有一个选项可以配置 SeekToCurrentBatchErrorHandler(使用 ListenerContainerCustomizer)来实现类似的功能,以便在 binder 中重试.

我尝试了同样的方法,但使用了 SeekToCurrentBatchErrorHandler,但它重试的时间超过了设置的 3 次。

  1. 我该怎么做? 我想重试整个批次。

  2. 如何将整个批次发送到 dlq 主题?就像我曾经将deliveryAttempt(retry)匹配到3然后发送到DLQ主题的记录监听器一样,签入监听器。

我已经检查了this link, which is exactly my issue,但是一个例子会很有帮助,使用这个库 spring-cloud-stream-kafka-binder,我可以实现这一点。请举例说明,我是新手。

目前我有以下代码。

@Configuration
public class ConsumerConfig {

  @Bean
  public ListenerContainerCustomizer<AbstractMessageListenerContainer<?, ?>> customizer() {
return (container, dest, group) -> {
    container.getContainerProperties().setAckOnError(false);
    
    SeekToCurrentBatchErrorHandler seekToCurrentBatchErrorHandler 
    = new SeekToCurrentBatchErrorHandler();
    seekToCurrentBatchErrorHandler.setBackOff(new FixedBackOff(0L, 2L));
    container.setBatchErrorHandler(seekToCurrentBatchErrorHandler);
    //container.setBatchErrorHandler(new BatchLoggingErrorHandler());
   };
 }
}

听者:

  @StreamListener(ActivityChannel.INPUT_CHANNEL)
  public void handleActivity(List<Message<Event>> messages,
                         @Header(name = KafkaHeaders.ACKNOWLEDGMENT) Acknowledgment 
                                                                     acknowledgment,
                         @Header(name = "deliveryAttempt", defaultValue = "1") int 
                                                                deliveryAttempt) {
  try {
    log.info("Received activity message with message length {}", messages.size());
    nodeConfigActivityBatchProcessor.processNodeConfigActivity(messages);
    acknowledgment.acknowledge();
    log.debug("Processed activity message {} successfully!!", messages.size());
  } catch (MessagePublishException e) {
    if (deliveryAttempt == 3) {
      log.error(
              String.format("Exception occurred, sending the message=%s to DLQ due to: ",
                      "message"),
              e);
      publisher.publishToDlq(EventType.UPDATE_FAILED, "message", e.getMessage());
    } else {
      throw e;
    }
  }
  }

看到@Gary 的回复后,添加了带有RetryingBatchErrorHandler 的ListenerContainerCustomizer @Bean,但无法导入该类。附上截图。

not able to import RetryingBatchErrorHandler

my spring cloud dependencies

【问题讨论】:

    标签: java spring apache-kafka spring-cloud-stream spring-cloud-stream-binder-kafka


    【解决方案1】:

    使用RetryingBatchErrorHandler 将整个批次发送到 DLT

    https://docs.spring.io/spring-kafka/docs/current/reference/html/#retrying-batch-eh

    使用RecoveringBatchErrorHandler 可以抛出BatchListenerFailedException 告诉它批处理中的哪条记录失败。

    https://docs.spring.io/spring-kafka/docs/current/reference/html/#recovering-batch-eh

    在这两种情况下都向错误处理程序提供DeadLetterPublishingRecoverer;在活页夹中禁用 DLT。

    编辑

    这是一个例子;它使用较新的函数式风格而不是已弃用的@StreamListener,但同样的概念也适用(但您应该考虑转向函数式风格)。

    @SpringBootApplication
    public class So69175145Application {
    
        public static void main(String[] args) {
            SpringApplication.run(So69175145Application.class, args);
        }
    
        @Bean
        ListenerContainerCustomizer<AbstractMessageListenerContainer<?, ?>> customizer(
                KafkaTemplate<byte[], byte[]> template) {
    
            return (container, dest, group) -> {
                container.setBatchErrorHandler(new RetryingBatchErrorHandler(new FixedBackOff(5000L, 2L),
                        new DeadLetterPublishingRecoverer(template,
                                (rec, ex) -> new TopicPartition("errors." + dest + "." + group, rec.partition()))));
            };
    
        }
    
        /*
         * DLT topic won't be auto-provisioned since enableDlq is false
         */
        @Bean
        public NewTopic topic() {
            return TopicBuilder.name("errors.so69175145.grp").partitions(1).replicas(1).build();
        }
    
        /*
         * Functional equivalent of @StreamListener
         */
        @Bean
        public Consumer<List<String>> input() {
            return list -> {
                System.out.println(list);
                throw new RuntimeException("test");
            };
        }
    
        /*
         * Not needed here - just to show we sent them to the DLT
         */
        @KafkaListener(id = "so69175145", topics = "errors.so69175145.grp")
        public void listen(String in) {
            System.out.println("From DLT: " + in);
        }
    
    }
    
    spring.cloud.stream.bindings.input-in-0.destination=so69175145
    spring.cloud.stream.bindings.input-in-0.group=grp
    spring.cloud.stream.bindings.input-in-0.content-type=text/plain
    
    spring.cloud.stream.bindings.input-in-0.consumer.batch-mode=true
    
    # for DLT listener
    spring.kafka.consumer.auto-offset-reset=earliest
    
    [foo]
    2021-09-14 09:55:32.838ERROR...
    ...
    [foo]
    2021-09-14 09:55:37.873ERROR...
    ...
    [foo]
    2021-09-14 09:55:42.886ERROR...
    ...
    From DLT: foo
    

    【讨论】:

    • 感谢您的快速回复,对于“RetryingBatchErrorHandler”没有给出示例,我如何将它添加到我在问题中提到的错误处理程序中。它是否适用于 spring-cloud-stream-binder-kafka 库。如果你能给我举个例子,那真的很有帮助。
    • 当我将鼠标悬停在它上面时,我无法创建这个对象 new RetryingBatchErrorHandler(new FixedBackOff(5000L, 2L),上面写着“无法解析符号'RetryingBatchErrorHandler”创建类 RetryingBatchErrorHandler。我不能导入这个类,我用的是spring.cloud.stream.binder.kafka的3.0.4.RELEASE版本,是不是版本问题?需要'spring-kafka'依赖吗??
    • 需要spring-kafka 2.3.7或更高版本;我不记得旧的 3.0.x 引入了哪个版本。我认为它在 3.0.9 中切换到稍后启动 - 尝试最新的 3.0.13 或升级到更新版本;最新的是 3.1.3。
    • 我尝试使用“spring-cloud-dependencies :Hoxton.SR12”这会拉取 spring.cloud.stream.binder.kafka.3.0.13 和“spring-cloud-dependencies:2020.0.3”其中拉 spring.cloud.stream.binder.kafka.3.1.3。但是还是不能导入这个类,是不是跟spring-boot-version有关系,current-version是2.2.4.RELEASE。如果它与spring-boot版本有关,那将是一个巨大的变化(我的问题会有其他解决方案吗)。
    • Boot 2.2 生命周期结束github.com/spring-projects/spring-boot/wiki/Supported-Versions;但是,2.2.4 引入了 spring-kafka 2.3.5(为时过早)。最终的 2.2.x 版本是 2.2.13;它引入了 spring-kafka 2.3.13,它有这个错误处理程序。即使在次要版本 (2.2.x) 中,您也应该始终尝试了解最新的引导版本。
    猜你喜欢
    • 1970-01-01
    • 2018-03-09
    • 2021-09-17
    • 1970-01-01
    • 2018-06-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 2023-01-03
    相关资源
    最近更新 更多