KafkaConsumer 0.10 сообщение об ошибке API Java: нет текущего назначения для раздела

Я использую KafkaConsumer 0.10 API-интерфейса Java. Я хочу потреблять из определенного раздела и определенного смещения. Я посмотрел вверх и обнаружил, что есть метод поиска, но его исключение. У кого-нибудь был подобный вариант использования или решение ?

код:

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)

2 ответов


перед seek() сначала надо subscribe() на тему или assign() раздел Темы для потребителя. Также имейте в виду, что subscribe() и assign() ленивы - таким образом, вам также нужно сделать "фиктивный вызов" в poll() прежде чем вы можете использовать seek().

Примечание: начиная с Кафки 2.0, новый poll(Duration timeout) является асинхронным, и не гарантируется, что у вас есть полное назначение, когда poll возвращает. Таким образом, вам может потребоваться проверить назначение перед использованием seek() и poll еще раз, чтобы обновить назначение. (Ср. КИП-266 дополнительные сведения)

если вы используете subscribe(), вы используете управление группами: таким образом, вы можете запустить несколько потребителей, используя тот же group.id и все разделы темы будут назначены равномерно всем потребителям в группе автоматически (каждый раздел будет назначен одному потребителю в группе).

если вы хотите прочитать конкретные разделы, вам нужно использовать ручное назначение через assign(). Это позволяет выполнять любое задание.

кстати: KafkaConsumer имеет очень длинный подробный класс JavaDoc, включая примеры. Стоит прочитать.


Если вы не хотите использовать () и получить записи карты, и изменить само смещение. Кафка версия 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
для мероприятий. Это гарантирует, что координатор известен и что потребитель присоединился к группе (если он использует управление группой). Это также обрабатывает периодические фиксации смещения, если они включены.