Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kafka 0.9-Java:消费者在应用程序重启期间跳过偏移_Java_Apache Kafka_Kafka Consumer Api - Fatal编程技术网

Kafka 0.9-Java:消费者在应用程序重启期间跳过偏移

Kafka 0.9-Java:消费者在应用程序重启期间跳过偏移,java,apache-kafka,kafka-consumer-api,Java,Apache Kafka,Kafka Consumer Api,我有一个具有以下属性的java应用程序 kafkaProperties = new Properties(); kafkaProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaBrokersList); kafkaProperties.put(ConsumerConfig.GROUP_ID_CONFIG, consumerGroupName); kafkaProperties.put(ConsumerConfig.KEY_DES

我有一个具有以下属性的java应用程序

kafkaProperties = new Properties();
kafkaProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaBrokersList);
kafkaProperties.put(ConsumerConfig.GROUP_ID_CONFIG, consumerGroupName);
kafkaProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
kafkaProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
kafkaProperties.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, consumerSessionTimeoutMs);
kafkaProperties.put(ConsumerConfig.MAX_PARTITION_FETCH_BYTES_CONFIG, maxPartitionFetchBytes);
kafkaProperties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
我已经创建了15个消费者线程,并让它们处理下面的可运行线程。我没有任何其他消费者使用此消费者组名称。

@覆盖
公开募捐{
试一试{
info(“启动ConsumerWorker,consumerId={}”,consumerId);
consumer.subscribe(Arrays.asList(kafkaTopic)、offsetLoggingCallback);
while(true){
布尔值isPollFirstRecord=true;
debug(“consumerId={};即将调用consumer.poll()…”,consumerId);
ConsumerRecords记录=consumer.poll(pollIntervalMs);
Map partitionOffsetMap=新HashMap();
对于(消费者记录:记录){
如果(isPollFirstRecord){
isPollFirstRecord=false;
info(“此轮询中分区{}的起始偏移量:{}”、record.partition()、record.offset());
}
messageProcessor.processMessage(record.value(),record.offset());
partitionOffsetMap.put(record.partition(),record.offset());
}
如果(!records.isEmpty()){
info(“调用分区/偏移量的提交:{}”,partitionOffsetMap);
consumer.commitAsync(offsetLoggingCallback);
}
}
}捕获(唤醒异常e){
warn(“ConsumerWorker[ConsumerRid={}]获得唤醒异常-正在退出…异常:{}”,
consumerId,e.getMessage());
}捕获(例外e){
logger.error(“ConsumerWorker[consumerId={}]获得异常-正在退出…异常:{}”,
consumerId,e.getMessage());
}最后{
warn(“ConsumerWorker[consumerId={}]正在关闭…”,consumerId);
consumer.close();
}
}
我还有一个OffsetCommitCallbackImpl,如下所示。它基本上以映射的形式维护分区及其提交的偏移量,并在提交偏移量时记录

@Override
    public void onComplete(Map<TopicPartition, OffsetAndMetadata> offsets, Exception exception) {
        if (exception == null) {
            offsets.forEach((topicPartition, offsetAndMetadata) -> {
                partitionOffsetMap.put(topicPartition, offsetAndMetadata);
                logger.info("Offset position during the commit for consumerId : {}, partition : {}, offset : {}", Thread.currentThread().getName(), topicPartition.partition(), offsetAndMetadata.offset());
            });
        } else {
            offsets.forEach((topicPartition, offsetAndMetadata) -> logger.error("Offset commit error, and partition offset info : {}, partition : {}, offset : {}", exception.getMessage(), topicPartition.partition(), offsetAndMetadata.offset()));
        }
    }  
@覆盖
未完成的公共空心(贴图偏移、异常){
if(异常==null){
offsets.forEach((topicPartition、offsetAndMetadata)->{
partitionOffsetMap.put(topicPartition、offsetAndMetadata);
info(“consumerId:{},分区:{},偏移:{},Thread.currentThread().getName(),topicPartition.partition(),offsetAndMetadata.Offset()提交期间的偏移位置”);
});
}否则{
Offset.forEach((topicPartition,offsetAndMetadata)->logger.error(“Offset commit error,and partition Offset info:{},partition:{},Offset:{}”,exception.getMessage(),topicPartition.partition(),offsetAndMetadata.Offset());
}
}  
问题/问题: 我注意到,每当我(重新启动)关闭并重新启动应用程序时,我都会错过事件/消息。所以当我仔细查看日志时。通过比较关机前提交的偏移量(使用offsetcommitcallback日志记录)与重启后提取处理的偏移量,我发现对于某些分区,我们没有提取关机前留下的偏移量。有时某些分区的开始偏移量比提交的偏移量多1000

注意:40个分区中有8个分区属于这种情况

如果仔细观察logginrun方法,有一个log语句,在调用async commit之前,我实际上在其中打印偏移量。例如,如果关闭前的最后一个日志显示分区1为10。重新启动后,我们正在为分区1处理的第一个偏移量大约为100。我确认我们确实丢失了90条信息


有谁能想出发生这种情况的原因吗?

您有多少消费者使用相同的群名?只有这一个。除此应用程序外,没有其他使用者。如果您使用的是高级使用者,则实际上不需要使用commitAsync()方法。HighLevelConsumer会自动处理所有提交,除非您将“自动提交”设置为false。@Misterbakal正如您在“我的属性”中看到的,我故意将“自动提交”设置为false。@Dhyan是否真的有必要?您有多少个组名相同的用户?仅此一个。除此应用程序外,没有其他使用者。如果您使用的是高级使用者,则实际上不需要使用commitAsync()方法。除非将“自动提交”设置为false,否则HighLevelConsumer将自动处理所有提交。@Misterbakal正如您在“我的属性”中看到的,我故意将“自动提交”设置为false。@Dhyan是否真的有必要?
@Override
    public void onComplete(Map<TopicPartition, OffsetAndMetadata> offsets, Exception exception) {
        if (exception == null) {
            offsets.forEach((topicPartition, offsetAndMetadata) -> {
                partitionOffsetMap.put(topicPartition, offsetAndMetadata);
                logger.info("Offset position during the commit for consumerId : {}, partition : {}, offset : {}", Thread.currentThread().getName(), topicPartition.partition(), offsetAndMetadata.offset());
            });
        } else {
            offsets.forEach((topicPartition, offsetAndMetadata) -> logger.error("Offset commit error, and partition offset info : {}, partition : {}, offset : {}", exception.getMessage(), topicPartition.partition(), offsetAndMetadata.offset()));
        }
    }