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
Java 多次呼叫消费者时如何重置卡夫卡消费者偏移量_Java_Apache Kafka - Fatal编程技术网

Java 多次呼叫消费者时如何重置卡夫卡消费者偏移量

Java 多次呼叫消费者时如何重置卡夫卡消费者偏移量,java,apache-kafka,Java,Apache Kafka,无论何时调用消费者,我都会尝试重置消费者偏移量,这样当我多次调用消费者时,它仍然可以读取生产者发送的记录。我正在设置props.put(“auto.offset.reset”,“最早”)并调用消费者。请参见tobegining(consumer.assignment())但当我第二次呼叫消费者时,它将不会收到任何记录。我怎样才能解决这个问题 public ConsumerRecords<String, byte[]> consumer(){ Properties pro

无论何时调用消费者,我都会尝试重置消费者
偏移量
,这样当我多次调用消费者时,它仍然可以读取生产者发送的记录。我正在设置props.put(“auto.offset.reset”,“最早”)并调用
消费者。请参见tobegining(consumer.assignment())但当我第二次呼叫消费者时,它将不会收到任何记录。我怎样才能解决这个问题

   public ConsumerRecords<String, byte[]> consumer(){
    Properties props = new Properties();
    props.put("bootstrap.servers", "localhost:9092");
    props.put("group.id", "test");
    //props.put("group.id", String.valueOf(System.currentTimeMillis()));
    props.put("auto.offset.reset","earliest");
    props.put("enable.auto.commit", "true");
    props.put("auto.commit.interval.ms", "1000");
    props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    props.put("value.deserializer", "org.apache.kafka.common.serialization.ByteArrayDeserializer");
    KafkaConsumer<String, byte[]> consumer = new KafkaConsumer<>(props);
    consumer.subscribe(Collections.singletonList("topiccc"));
    ConsumerRecords<String, byte[]> records = consumer.poll(100);
    consumer.seekToBeginning(consumer.assignment());
   /* List<byte[]> videoContents = new ArrayList<byte[]>();
    for (ConsumerRecord<String, byte[]> record : records) {
        System.out.printf("offset = %d, key = %s, value = %s\n", record.offset(), record.key(), record.value());
        videoContents.add(record.value());
    }*/

    return records;
} 

public String producer(@RequestParam("message") String message) {
    Map<String, Object> props = new HashMap<>();
    // list of host:port pairs used for establishing the initial connections to the Kakfa cluster
    props.put("bootstrap.servers", "localhost:9092");
    props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
    props.put("value.serializer", "org.apache.kafka.common.serialization.ByteArraySerializer");
    Producer<String, byte[]> producer = new KafkaProducer<>(props);
    Path path = Paths.get("C:/Programming Files/video-2012-07-05-02-29-27.mp4");
    ProducerRecord<String, byte[]> record = null;
    try {

        record = new ProducerRecord<>("topiccc", "keyyyyy"
                , Files.readAllBytes(path));

    } catch (IOException e) {
        e.printStackTrace();
    }
    producer.send(record);
    producer.close();
    //kafkaSender.send(record);

    return "Message sent to the Kafka Topic java_in_use_topic Successfully";
}
公共消费者记录消费者(){
Properties props=新属性();
put(“bootstrap.servers”,“localhost:9092”);
props.put(“group.id”、“test”);
//put(“group.id”,String.valueOf(System.currentTimeMillis());
道具放置(“自动偏移重置”、“最早”);
props.put(“enable.auto.commit”、“true”);
props.put(“auto.commit.interval.ms”,“1000”);
put(“key.deserializer”、“org.apache.kafka.common.serialization.StringDeserializer”);
put(“value.deserializer”、“org.apache.kafka.common.serialization.ByteArraydSerializer”);
卡夫卡消费者=新卡夫卡消费者(道具);
consumer.subscribe(Collections.singletonList(“topiccc”);
ConsumerRecords记录=consumer.poll(100);
consumer.seektobegining(consumer.assignment());
/*List videoContents=new ArrayList();
对于(消费者记录:记录){
System.out.printf(“偏移量=%d,键=%s,值=%s\n”,record.offset(),record.key(),record.value());
videoContents.add(record.value());
}*/
退货记录;
} 
公共字符串生成器(@RequestParam(“message”)字符串消息){
Map props=newhashmap();
//主机列表:用于建立到Kakfa集群的初始连接的端口对
put(“bootstrap.servers”,“localhost:9092”);
put(“key.serializer”、“org.apache.kafka.common.serialization.StringSerializer”);
put(“value.serializer”、“org.apache.kafka.common.serialization.ByteArraySerializer”);
制作人=新卡夫卡制作人(道具);
Path Path=Path.get(“C:/Programming Files/video-2012-07-05-02-29-27.mp4”);
ProducerRecord记录=null;
试一试{
记录=新产品记录(“topiccc”、“keyyyyy”
,Files.readAllBytes(路径));
}捕获(IOE异常){
e、 printStackTrace();
}
制作人。发送(记录);
producer.close();
//卡夫卡森德。发送(记录);
返回“发送到卡夫卡主题java_in_use_主题的消息成功”;
}

我通常使用不同的group.id创建一个新的消费者,以便再次读取记录。 那么就这样做吧:

props.put("group.id", Instant.now().getEpochSecond());

有一种解决方法(虽然不是生产解决方案),即每次消费时更改
group.id
配置值。在许多情况下,将
auto.offset.reset
设置为
earlime
是不够的。

根据卡夫卡Java代码,on auto_offset\u reset\u配置说明如下:

如果Kafka中没有初始偏移量,或者服务器上不再存在当前偏移量(例如,因为该数据已被删除),该怎么办:
  • 最早:自动将偏移量重置为最早偏移量
  • 最新:自动将偏移量重置为最新偏移量
  • 无:如果未找到消费者组的以前偏移量,则向消费者抛出异常
  • 其他:向消费者抛出异常。
  • 这可以在GitHub中找到:

    我们可以从他们的评论中看到,该设置仅在偏移量不在服务器上时使用。在这个问题中,偏移量是从服务器检索的,这就是为什么偏移量不会重置为起始偏移量,而是保持在最后一个偏移量,从而使它看起来没有更多的记录

    您需要在服务器端显式重置偏移量,以按照问题中的要求修复此问题

    下面是另一个答案,描述了如何做到这一点。

    这是一段允许我重置偏移量的代码。注意:如果调用subscribe方法,则不能调用seektobegining。只有我自己使用assign方法分配分区,我才能让它工作。可怜

    // Create the consumer:
    final Consumer<String, DataRecord> consumer = new KafkaConsumer<>(props);
    
    // Get the partitions that exist for this topic:
    List<PartitionInfo> partitions = consumer.partitionsFor(topic);
    
    // Get the topic partition info for these partitions:
    List<TopicPartition> topicPartitions = partitions.stream().map(info -> new TopicPartition(info.topic(), info.partition())).collect(Collectors.toList());
    
    // Assign all the partitions to the topic so that we can seek to the beginning:
    // NOTE: We can't use subscribe if we use assign, but we can't seek to the beginning if we use subscribe.
    consumer.assign(topicPartitions);
    
    // Make sure we seek to the beginning of the partitions:
    consumer.seekToBeginning(topicPartitions);
    
    //创建消费者:
    最终消费者=新卡夫卡消费者(道具);
    //获取此主题存在的分区:
    List partitions=consumer.partitions(主题);
    //获取这些分区的主题分区信息:
    List topicPartitions=partitions.stream().map(info->newtopicpartition(info.topic(),info.partition()).collect(Collectors.toList());
    //将所有分区分配给主题,以便我们可以从头开始:
    //注意:如果使用assign,我们不能使用subscribe,但是如果使用subscribe,我们不能从头开始。
    consumer.assign(主题分区);
    //确保我们搜索到分区的开头:
    消费者。参见主题分类;
    

    是的,实现一个看似基本的用例似乎非常复杂。这可能表明整个卡夫卡世界似乎只想读一次流。

    当您希望一条消息被消费者多次消费时,理想的方法是创建具有不同消费群体的消费者,以便可以消费相同的消息

    但是,如果希望同一消费者多次使用同一消息,则可以使用commit和offset 您可以将auto.commit设置得非常高,或者禁用它,然后按照您的逻辑进行提交

    有关更多详细信息,请参阅此
    此javadoc提供了有关如何手动管理偏移量的详细信息

    如果您尝试手动执行此操作,是否有效?例如,
    kafka-consumer-groups.bat——引导服务器kafka主机:9092——分组我的组——重置偏移量——到最早——所有主题——执行
    我需要在程序中执行,但在线程“main”中出现异常org.apache.kafka.common.config.ConfigException:bootstrap.servers中没有提供可解析的引导URL,尽管我已将其设置为“localhost:9092”,但您需要发布完整代码。@giorgosmyriantous我添加了