web-dev-qa-db-ja.com

KafkaConsumer 0.10 Java APIエラーメッセージ:パーティションの現在の割り当てがありません

私はKafkaConsumer 0.10 Java apiを使用しています。特定のパーティションと特定のオフセットから消費したいのですが。ユースケースまたはソリューション?

コード:

KafkaConsumer<String, byte[]> consumer = new KafkaConsumer<>(consumerProps);
consumer.seek(new TopicPartition("mytopic", 1), 4);

例外

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)
17
colossal

seek()を実行する前に、まずトピックにsubscribe()する必要がありますorコンシューマーへのトピックのassign()パーティション。また、subscribe()assign()は遅延していることに注意してください。したがって、poll()を使用する前に、seek()に対して「ダミー呼び出し」を行う必要もあります。

注:Kafka 2.0の時点で、新しいpoll(Duration timeout)は非同期であり、pollが戻ったときに完全な割り当てがあることは保証されていません。 seek()を使用する前に割り当てを確認し、またpollを使用して割り当てを更新してください(詳細については KIP-266

subscribe()を使用する場合、グループ管理を使用します。したがって、同じgroup.idを使用して複数のコンシューマーを起動でき、トピックのすべてのパーティションがグループ内のすべてのコンシューマーに自動的に均等に割り当てられます(各パーティションはグループ内の単一の消費者に割り当てられます)。

特定のパーティションを読み取りたい場合は、assign()経由で手動割り当てを使用する必要があります。これにより、必要な割り当てを行うことができます。

ところで:KafkaConsumerには、例を含む非常に長い詳細なクラスJavaDocがあります。それを読む価値があります。

38
Matthias J. Sax

poll()を使用しないでマップレコードを取得し、オフセット自体を変更する場合。 Kafkaバージョン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

コーディネーターイベントのポーリング。これにより、コーディネーターが認識され、コンシューマーがグループに参加していることが保証されます(グループ管理を使用している場合)。これは、定期的なオフセットコミットが有効になっている場合も処理します。

1
Adam111p