我对卡夫卡比较新。
我们处理来自kafka的消息并将它们持久化到数据库。如果将它们持久化到数据库时出现故障,则不会提交消息。
我的问题是: 我们想知道如何重新使用未提交的消息?
我尝试了一些方法。
在这种情况下最佳做法是什么?提前致谢。
答案 0 :(得分:0)
如果您使用spring-Kafka项目,则可以使用ContainerStoppingErrorHandler这将导致错误地停止容器。下面是示例KafkaListener方法,该方法将在DataAccessException上重试并在将耗尽的传递错误退回到下面的Config类中定义的错误处理程序之后
@KafkaListener(topics = ("${spring.kafka.consumer.topic}"), containerFactory = "kafkaManualAckListenerContainerFactory")
@Retryable(include = DataAccessException.class, backoff = @Backoff(delay = 20000, multiplier = 3))
public void onMessage(List<ConsumerRecord<String, String>> recordList,
Acknowledgment acknowledgment, Consumer<?, ?> consumer) throws DataAccessException {
try {
kafkaSinkController.saveToDb(recordList);
acknowledgment.acknowledge();
LOGGER.info("Message Saved DB");
} catch (Exception e) {
LOGGER.error("Other than db exception ", e)
}
}
配置bean
@Bean
KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, String>>
kafkaManualAckListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, String> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(new DefaultKafkaConsumerFactory<String, String>(consumerConfig));
factory.setConcurrency(concurrentConsumerCount);
factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);
factory.getContainerProperties().setBatchErrorHandler(new ContainerStoppingBatchErrorHandler());
//It will stop container and thus consumer will stop listening
factory.setBatchListener(true);
return factory;
}
当你想开始重新消费消息时,可以使用KafkaListenerEndpointRegistry启动容器,下面的示例方法用于引用,一旦数据库启动,可以通过以此方法的端点公开的方式以编程方式调用。
@Autowired
KafkaListenerEndpointRegistry registry;
public void startContainer() {
try {
registry.start();
} catch (Exception ex) {
//Todo
}
}
以上样本依赖于所有弹簧组件,但如果没有spring-kafka项目,也可以实现相同的目标。
答案 1 :(得分:0)
捕获异常并将消息发布到另一个Kafka重试主题,该主题将由另一个使用者单独处理。