web-dev-qa-db-fra.com

KafkaConsumer 0.10 Java API: Aucune affectation actuelle pour la partition

J'utilise KafkaConsumer 0.10 Java api. Je veux consommer à partir d'une partition spécifique et d'un décalage spécifique. J'ai recherché et trouvé qu'il existe une méthode de recherche mais son lançant une exception. cas d'utilisation ou solution?

Code:

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

Exception

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

Avant de pouvoir seek() vous devez d'abord subscribe() à un sujet ouassign() partition d'un sujet au consommateur. Gardez également à l'esprit que subscribe() et assign() sont paresseux - vous devez donc également effectuer un "appel factice" à poll() avant de pouvoir utiliser seek().

Remarque: à partir de Kafka 2.0, la nouvelle poll(Duration timeout) est asynchrone et il n'est pas garanti que vous ayez une affectation complète lorsque poll revient. Ainsi, vous pourriez besoin de vérifier votre affectation avant d'utiliser seek() et également poll pour actualiser l'affectation. (Cf. KIP-266 pour plus de détails)

Si vous utilisez subscribe(), vous utilisez la gestion de groupe: ainsi, vous pouvez démarrer plusieurs consommateurs en utilisant le même group.id Et toutes les partitions du sujet seront affectées de manière égale à tous les consommateurs du groupe automatiquement ( chaque partition sera assignée à un seul consommateur du groupe).

Si vous souhaitez lire des partitions spécifiques, vous devez utiliser l'attribution manuelle via assign(). Cela vous permet de faire toute affectation que vous souhaitez.

Btw: KafkaConsumer a une très longue classe JavaDoc détaillée incluant des exemples. Cela vaut la peine de le lire.

38
Matthias J. Sax

Si vous ne souhaitez pas utiliser poll () et récupérer les enregistrements de carte et modifier le décalage lui-même. Kafka version 0.11 Essayez ceci:

...
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

Sondage pour les événements de coordination. Cela garantit que le coordinateur est connu et que le consommateur a rejoint le groupe (s'il utilise la gestion de groupe). Cela gère également les validations de décalage périodiques si elles sont activées.

1
Adam111p