【问题标题】:How does AckMode as BATCH work with max.poll.interval.ms work and enable.auto.commit as 'false'?AckMode as BATCH 如何与 max.poll.interval.ms 一起工作并将 enable.auto.commit 设置为“false”?
【发布时间】:2020-04-15 00:09:12
【问题描述】:

我正在使用 spring-kafka '2.1.7.RELEASE' 并且我试图了解 max.poll.interval.ms 如何将 AckMode 作为 BATCH 并将 enable.auto.commit 作为 'false' 工作。这是我的消费者设置。

    public Map<String, Object> setConsumerConfigs() {

           Map<String, Object> configs = = new HashMap<>();

           configs.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
           configs.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");

           configs.put(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, "400000");

           configs.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, ErrorHandlingDeserializer2.class);
           configs.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ErrorHandlingDeserializer2.class);

           configs.put(ErrorHandlingDeserializer2.KEY_DESERIALIZER_CLASS, stringDeserializerClass);
           configs.put(ErrorHandlingDeserializer2.VALUE_DESERIALIZER_CLASS, kafkaAvroDeserializerClass.getName());

           configs.setPartitionAssignmentStrategyConfig(Collections.singletonList(RoundRobinAssignor.class));

           // Set this to true so that you will have consumer record value coming as your pre-defined contract instead of a generic record
           sapphireKafkaConsumerConfig.setSpecificAvroReader("true");
       }

这是我的出厂设置

        @Bean
         public <K,V> ConcurrentKafkaListenerContainerFactory<String, Object> kafkaListenerContainerFactory() {
           ConcurrentKafkaListenerContainerFactory<String, Object> factory = new ConcurrentKafkaListenerContainerFactory<>();
           factory.setConsumerFactory(new DefaultKafkaConsumerFactory<>(getConsumerConfigs));
           factory.getContainerProperties().setMissingTopicsFatal(false);

           factory.getContainerProperties().setAckMode(AckMode.BATCH);

           factory.setErrorHandler(myCustomKafkaSeekToCurrentErrorHandler);
           factory.setRetryTemplate(retryTemplate());
           factory.setRecoveryCallback(myCustomKafkaRecoveryCallback);
           factory.setStatefulRetry(true);
           return factory;
         }

         public RetryTemplate retryTemplate() {
            RetryTemplate retryTemplate = new RetryTemplate();
            retryTemplate.setListeners(new RetryListener[]{myCustomKafkaRetryListener});
            retryTemplate.setRetryPolicy(myCustomKafkaConsumerRetryPolicy);

            FixedBackOffPolicy backOff = new FixedBackOffPolicy();
            backOff.setBackOffPeriod(1000);
            retryTemplate.setBackOffPolicy(backOff);


            return retryTemplate;
          }

这是我的消费者,我添加了 2 分钟的延迟

@KafkaListener(topics = TestConsumerConstants.CONSUMER_LONGRUNNING_RECORDS_PROCESSSING_TEST_TOPIC
      , clientIdPrefix = "CONSUMER_LONGRUNNING_RECORDS_PROCESSSING"
      , groupId = "kafka-lib-comp-test-consumers")
  public void consumeLongRunningRecord(ConsumerRecord message) throws InterruptedException {
    System.out.println(String.format("\n \n Received message at %s offset %s of partition %s of topic %s with key %s \n\n", DateTime.now(),
        message.offset(), message.partition(), message.topic(), message.key()));

    TimeUnit.MINUTES.sleep(2);

    System.out.println(String.format("\n \n Processing done for the message at %s offset %s of partition %s of topic %s with key %s \n\n", DateTime.now(),
        message.offset(), message.partition(), message.topic(), message.key()));
  }

现在,我发布了 5 条消息,并观察到它处理了所有记录,没有任何问题。但是,如果我将 AckMode 设置为 RECORD,它会在处理第 4 条消息后提交偏移量时抛出错误,然后处理相同的消息两次(这是预期的)。

根据 spring-kafka 文档,当 poll() 返回的所有记录都被处理后,AckMode = BATCH 将提交偏移量。

现在,我的问题是,AckMode 如何在通过 max.poll.interval.ms 后改变行为而不引起重新平衡?请帮我理解。

Caused by: org.apache.kafka.clients.consumer.CommitFailedException: Commit cannot be completed since the group has already rebalanced and assigned the partitions to another member. This means that the time between subsequent calls to poll() was longer than the configured max.poll.interval.ms, which typically implies that the poll loop is spending too much time message processing. You can address this either by increasing the session timeout or by reducing the maximum size of batches returned in poll() with max.poll.records.

【问题讨论】:

    标签: spring-kafka


    【解决方案1】:

    我认为这个帖子将有助于澄清一些事情,如果不是完全的话,

    Difference between session.timeout.ms and max.poll.interval.ms for Kafka 0.10.0.0 and later versions

    【讨论】:

    • 感谢@Rohit 的回复。我的问题是关于 max.poll.interval.ms 和 spring-kafka 的 AckMode 的组合
    【解决方案2】:

    改变 ack 模式不会影响再平衡; max.poll.interval.ms 是调用 poll() 之间允许的时间,不会随 ack 模式而改变。

    因为你的间隔是 6.67 分钟;我希望它也会在 BATCH 模式下失败;也许民意调查只返回了该测试的 2 或 3 条记录,而当您测试 RECORD 模式时返回了 4 或 5 条记录。

    您可以通过为org.springframework.kafka 启用 DEBUG 日志记录来获取轮询返回的记录数。

    【讨论】:

    • 好的,我试试。感谢您的回复。
    猜你喜欢
    • 2017-10-14
    • 2017-08-30
    • 1970-01-01
    • 2013-06-22
    • 2021-12-02
    • 2013-04-22
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多