Java 如何使用poll()检查KafkaConsumer是否仍有分配的分区,而不读取更多数据

Java 如何使用poll()检查KafkaConsumer是否仍有分配的分区,而不读取更多数据,java,apache-kafka,kafka-consumer-api,Java,Apache Kafka,Kafka Consumer Api,在我的KafkaConsumer应用程序中,我想使用poll()读取一批消息并对其进行处理。但处理可能会失败。在这种情况下,我希望重试直到成功,但只有在使用者仍然拥有分区时才重试。我不想经常调用poll(),因为我不想读取更多数据 这是一段代码片段: consumer = new KafkaConsumer<>(consumerConfig); try { consumer.subscribe(config.topics() /** Callback does not wor

在我的KafkaConsumer应用程序中,我想使用poll()读取一批消息并对其进行处理。但处理可能会失败。在这种情况下,我希望重试直到成功,但只有在使用者仍然拥有分区时才重试。我不想经常调用poll(),因为我不想读取更多数据

这是一段代码片段:

consumer = new KafkaConsumer<>(consumerConfig);
try {
    consumer.subscribe(config.topics() /** Callback does not work as I do not call poll in between */ );
    while (true) {
        ConsumerRecords<byte[], Value> values = consumer.poll(10000);
        while (/* I am still owner of partitions */) {
            try {
                process(values);
            } catch (Exception e) {
                log.error("I dont care, just retry while I own the partitions", e)
            }
        }
    }
} catch (WakeupException e) {
    // shutting down
} finally {
    consumer.close();
} 
consumer=新卡夫卡消费者(consumerConfig);
试一试{
consumer.subscribe(config.topics()/**回调不起作用,因为我不在其间调用poll*/);
while(true){
ConsumerRecords值=consumer.poll(10000);
而(/*我仍然是分区的所有者*/){
试一试{
过程(价值观);
}捕获(例外e){
error(“我不在乎,只要在我拥有分区时重试”,e)
}
}
}
}捕获(唤醒异常e){
//关闭
}最后{
consumer.close();
} 

有一个回调方法,它告诉您消费者分区分配将被撤销的时间。除非收到OnPartitionReversed()事件,否则请继续处理消息


直接调用
assignment()
怎么样


我得出结论,如果不阅读当前kafka consumer 10.2.x的消息,就不可能调用poll()。但是,在处理失败后可以更新偏移量。所以我更新了offset,就好像这些消息从未被读取过一样

while (!stopped) {
   ConsumerRecords<byte[], Value> values = consumer.poll(timeout);
    try {
        process(values);
    } catch (Exception e) {
        rewind(records);
        // Ensure a delay after errors to let dependencies recover
        Thread.sleep(delay);
    }
}
while(!stopped){
ConsumerRecords值=consumer.poll(超时);
试一试{
过程(价值观);
}捕获(例外e){
倒带(记录);
//确保错误后的延迟,以便恢复依赖关系
睡眠(延迟);
}
}
倒带方法是

private void rewind(ConsumerRecords<byte[], Value> records) {
    records.partitions().forEach(partition -> {
        long offset = records.records(partition).get(0).offset();   
        consumer.seek(partition, offset);
    });
}
private void回放(消费者记录){
records.partitions().forEach(分区->{
长偏移量=records.records(分区).get(0.offset();
consumer.seek(分区、偏移);
});
}

它解决了最初的问题

,但是如何调用这个回调方法呢?从哪个线程?我相信它是由卡夫卡消费者客户端主线程调用的。试试看。建议您无论如何都实现此回调,这样就不会丢失偏移量,并在重新平衡后重新处理消息在循环中,不是吗?是的,但它没有被阻止,所以它仍然可以接收异步回调。如果您的进程(值)在外部资源上被阻止,则您可能希望在一个或多个与使用者线程分开的处理线程中进行处理。是否从主使用者线程的poll()调用内部调用回调?这正是我要避免的,因为如果消费者仍然订阅分区,我不想调用poll()并读取更多数据。或者它是从一个单独的线程调用的?然后我想阅读关于kafka消费线程的文档,因为我只知道主消费线程和healthcheck线程。但是healthcheck线程不应该调用回调。我尝试了,但是看起来assignment()返回了最后分配的分区,但是没有检查是否发生了重新平衡以及分区是否被撤销