Spring kafka Batch Listener-在Batch中手动提交偏移

时间:2017-12-13 16:22:17

标签: spring spring-boot spring-kafka

我正在实现spring kafka批量监听器,它从Kafka主题读取消息列表并将数据发布到REST服务。 我想了解在REST服务发生故障的情况下的偏移管理,不应提交批处理的偏移量,并且应该为下一次轮询处理消息。我已经阅读了spring kafka文档,但是理解Listener Error Handler和Seek对批量当前容器错误处理程序之间的区别存在困惑。我使用的是spring-boot-2.0.0.M7版本,下面是我的代码。

Listener Config:

@Bean
    KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, String>> kafkaListenerContainerFactory() {
        ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory());

        factory.setConcurrency(Integer.parseInt(env.getProperty("spring.kafka.listener.concurrency")));
        // factory.getContainerProperties().setPollTimeout(3000);
        factory.getContainerProperties().setBatchErrorHandler(kafkaErrorHandler());

        factory.getContainerProperties().setAckMode(AckMode.BATCH);
        factory.setBatchListener(true);
        return factory;
    }
@Bean
    public Map<String, Object> consumerConfigs() {
        Map<String, Object> propsMap = new HashMap<>();
        propsMap.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, env.getProperty("spring.kafka.bootstrap-servers"));
        propsMap.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,
                env.getProperty("spring.kafka.consumer.enable-auto-commit"));
        propsMap.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG,
                env.getProperty("spring.kafka.consumer.auto-commit-interval"));
        propsMap.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, env.getProperty("spring.kafka.session.timeout"));
        propsMap.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        propsMap.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        propsMap.put(ConsumerConfig.GROUP_ID_CONFIG, env.getProperty("spring.kafka.consumer.group-id"));
        return propsMap;
    }

Listener Class:

@KafkaListener(topics = "${spring.kafka.consumer.topic}", containerFactory = "kafkaListenerContainerFactory")
    public void listen(List<String> payloadList) throws Exception {
        if (payloadList.size() > 0)
            //Post to the service
    }

Kafka Error Handler:

public class KafkaErrorHandler implements BatchErrorHandler {

    private static Logger LOGGER = LoggerFactory.getLogger(KafkaErrorHandler.class);

    @Override
    public void handle(Exception thrownException, ConsumerRecords<?, ?> data) {
        LOGGER.info("Exception occured while processing::" + thrownException.getMessage());

            }

}

如何处理Kafka监听器,以便在处理批处理记录期间发生某些事情时,我不会丢失数据。

1 个答案:

答案 0 :(得分:0)

使用Apache Kafka,我们永远不会丢失数据。分区日志确实存在偏移以寻找任意位置。

另一方面,当我们从分区中消耗记录时,不需要提交它们的偏移量 - 当前的消费者将状态保存在内存中。当目前的消费者死亡时,我们只需要为同一组中的其他新消费者提供服务。与错误无关,当前消费者总是继续轮询其当前内存中偏移量后面的新数据。

因此,要在同一个消费者中重新处理相同的数据,我们必须使用seek操作将消费者移回所需的位置。这就是Spring Kafka介绍SeekToCurrentErrorHandler

的原因
  

这允许实现寻找所有未处理的主题/分区,以便下次轮询检索当前记录(以及其他剩余的记录)。 SeekToCurrentErrorHandler就是这样做的。

https://docs.spring.io/spring-kafka/reference/htmlsingle/#_seek_to_current_container_error_handlers