我正在实现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监听器,以便在处理批处理记录期间发生某些事情时,我不会丢失数据。
答案 0 :(得分:0)
使用Apache Kafka,我们永远不会丢失数据。分区日志确实存在偏移以寻找任意位置。
另一方面,当我们从分区中消耗记录时,不需要提交它们的偏移量 - 当前的消费者将状态保存在内存中。当目前的消费者死亡时,我们只需要为同一组中的其他新消费者提供服务。与错误无关,当前消费者总是继续轮询其当前内存中偏移量后面的新数据。
因此,要在同一个消费者中重新处理相同的数据,我们必须使用seek
操作将消费者移回所需的位置。这就是Spring Kafka介绍SeekToCurrentErrorHandler
:
这允许实现寻找所有未处理的主题/分区,以便下次轮询检索当前记录(以及其他剩余的记录)。
SeekToCurrentErrorHandler
就是这样做的。
https://docs.spring.io/spring-kafka/reference/htmlsingle/#_seek_to_current_container_error_handlers