KafkaConsumer 0.10 Java API错误消息:没有分区的当前分配

KafkaConsumer 0.10 Java API错误消息:没有分区的当前分配,java,kafka-consumer-api,Java,Kafka Consumer Api,我正在使用KafkaConsumer 0.10 Java api。我想使用特定分区和特定偏移量的数据。我查了一下,发现有一个seek方法,但它抛出了一个异常。有人有类似的用例或解决方案吗 代码: 在您可以seek()之前,您首先需要subscribe()到主题或assign()将主题的分区分配给消费者。还要记住,subscribe()和assign()是懒惰的——因此,在使用seek()之前,还需要对poll()执行一个“伪调用” 注意:从Kafka 2.0开始,新的poll(持续时间超时)是异

我正在使用KafkaConsumer 0.10 Java api。我想使用特定分区和特定偏移量的数据。我查了一下,发现有一个seek方法,但它抛出了一个异常。有人有类似的用例或解决方案吗

代码:

在您可以
seek()
之前,您首先需要
subscribe()
到主题
assign()
将主题的分区分配给消费者。还要记住,
subscribe()
assign()
是懒惰的——因此,在使用
seek()
之前,还需要对
poll()
执行一个“伪调用”

注意:从Kafka 2.0开始,新的
poll(持续时间超时)
是异步的,不能保证在
poll
返回时有完整的赋值。因此,在使用
seek()
之前,您可能需要检查您的作业,并再次使用
poll
刷新作业。(详情请参阅)

如果使用
subscribe()
,则使用组管理:因此,您可以使用相同的
group.id
启动多个使用者,主题的所有分区将自动平均分配给组中的所有使用者(每个分区将分配给组中的单个使用者)

如果要读取特定分区,需要通过
assign()
使用手动分配。这允许你做任何你想要的任务


顺便说一句:
KafkaConsumer
有一个非常长的详细类JavaDoc,包括示例。值得一读。

如果您不想使用poll()检索地图记录,并更改偏移量本身。 卡夫卡版本0.11 试试这个:

...
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");    
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);    
consumer.subscribe(Arrays.asList("Test_topic1", "Test_topic2"));
List<TopicPartition> partitions =consumer.partitionsFor("Test_topic1").stream().map(part->{TopicPartition tp = new TopicPartition(part.topic(),part.partition()); return tp;}).collect(Collectors.toList());
Field coordinatorField = consumer.getClass().getDeclaredField("coordinator"); 
coordinatorField.setAccessible(true);    

ConsumerCoordinator coordinator = (ConsumerCoordinator)coordinatorField.get(consumer);
coordinator.poll(new Date().getTime(), 1000);//Watch out for your local date and time settings
consumer.seekToBeginning(partitions); //or other seek
。。。
put(“value.deserializer”、“org.apache.kafka.common.serialization.StringDeserializer”);
卡夫卡消费者=新卡夫卡消费者(道具);
consumer.subscribe(Arrays.asList(“Test_topic1”、“Test_topic2”);
List partitions=consumer.partitions for(“Test_topic1”).stream().map(part->{TopicPartition tp=new TopicPartition(part.topic(),part.partition());return tp;}).collect(collector.toList());
字段coordinatorField=consumer.getClass().getDeclaredField(“协调员”);
coordinatorField.setAccessible(true);
ConsumerCoordinator coordinator=(ConsumerCoordinator)coordinatorField.get(consumer);
coordinator.poll(新日期().getTime(),1000)//注意您的本地日期和时间设置
消费者。请参见目标划分(分区)//或其他寻求

为协调人事件进行投票。这可确保协调员是已知的,并且消费者已加入该组(如果使用组管理)。如果启用了定期偏移提交,这也会处理它们。

请使用消费者。分配消费者。查找消费者。订阅消费者。


这些更改后,它将正常执行。

谢谢。它起作用了:)通过assign()和seek()的组合,我想你指的是
group.id
,而不是
application.id
,在这里回答太多的卡夫卡斯特伦问题。。。谢谢你指出@automaticgiant@MatthiasJ.Sax还请记住,subscribe()和assign()是惰性的——因此,在使用seek()之前,还需要对poll()执行“伪调用”。“subscribe和assign的惰性类型如何影响代码?”?如果我不使用类似于
poll(0)
的虚拟轮询,该怎么办?我想对于assign(),这是可以的。但是对于
subscribe()
,只要您不调用
poll()
,您就没有加入消费者组,也没有分配任何分区。因此,您将以问题中所示的异常结束。不清楚。代码示例?
java.lang.IllegalStateException: No current assignment for partition mytopic-1
    at org.apache.kafka.clients.consumer.internals.SubscriptionState.assignedState(SubscriptionState.java:251)
    at org.apache.kafka.clients.consumer.internals.SubscriptionState.seek(SubscriptionState.java:276)
    at org.apache.kafka.clients.consumer.KafkaConsumer.seek(KafkaConsumer.java:1135)
    at xx.xxx.xxx.Test.main(Test.java:182)
...
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");    
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);    
consumer.subscribe(Arrays.asList("Test_topic1", "Test_topic2"));
List<TopicPartition> partitions =consumer.partitionsFor("Test_topic1").stream().map(part->{TopicPartition tp = new TopicPartition(part.topic(),part.partition()); return tp;}).collect(Collectors.toList());
Field coordinatorField = consumer.getClass().getDeclaredField("coordinator"); 
coordinatorField.setAccessible(true);    

ConsumerCoordinator coordinator = (ConsumerCoordinator)coordinatorField.get(consumer);
coordinator.poll(new Date().getTime(), 1000);//Watch out for your local date and time settings
consumer.seekToBeginning(partitions); //or other seek