Пожалуйста, кто-нибудь скажет мне, как читать сообщения с использованием API-интерфейса Kafka с самого начала каждый раз, когда я запускаю потребительскую банку.
Как читать данные с использованием Kafka Consumer API с самого начала?
Ответ 1
Это работает с потребителем 0.9.x. В основном, когда вы создаете пользователя, вам нужно назначить идентификатор группы потребителей этому потребителю, используя свойство ConsumerConfig.GROUP_ID_CONFIG
. Генерируйте идентификатор группы потребителей произвольно каждый раз, когда вы запускаете пользователя, делающего что-то вроде этого properties.put(ConsumerConfig.GROUP_ID_CONFIG, UUID.randomUUID().toString());
(свойства - это экземпляр java.util.Properties, который вы передадите конструктору new KafkaConsumer(properties)
).
Генерация клиента случайным образом означает, что новая группа потребителей не имеет никакого смещения, связанного с ней в kafka. Итак, после этого мы должны установить политику для этого сценария. Поскольку в документации для свойства auto.offset.reset
указано:
Что делать, если в Kafka нет начального смещения или если текущее смещение больше не существует на сервере (например, поскольку эти данные были удалены):
- самое раннее: автоматически reset смещение к самому раннему смещению
- последним: автоматически reset смещение до последнего смещения
- none: исключить исключение для потребителя, если не найдено никакого предыдущего смещения или группа потребителей
- что-нибудь еще: исключение для потребителя.
Итак, из перечисленных выше опций нам нужно выбрать политику earliest
, чтобы новая группа потребителей начиналась с самого начала каждый раз.
Ваш код в java будет выглядеть примерно так:
properties.put(ConsumerConfig.GROUP_ID_CONFIG, UUID.randomUUID().toString());
properties.put(ConsumerConfig.CLIENT_ID_CONFIG, "your_client_id");
properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
consumer = new KafkaConsumer(properties);
Единственное, что вам нужно выяснить сейчас, - это когда у нескольких потребителей, принадлежащих к одной и той же группе потребителей, но распределенных, как генерировать случайный идентификатор и распространять его между этими экземплярами, чтобы все они принадлежали одному и тому же потребителю группа.
Надеюсь, что это поможет!
Ответ 2
Один из вариантов сделать это будет иметь уникальный идентификатор группы при каждом запуске, что будет означать, что Kafka будет отправлять вам сообщения в теме с самого начала. Сделайте что-то подобное, когда вы устанавливаете свои свойства для KafkaConsumer
:
properties.put(ConsumerConfig.GROUP_ID_CONFIG, UUID.randomUUID().toString());
Другой вариант - использовать consumer.seekToBeginning(consumer.assignment())
но это не сработает, если Kafka сначала не получит сердцебиение от вашего потребителя, заставив потребителя вызвать метод poll. Так что вызовите poll()
, затем выполните seekToBeginning()
а затем снова вызовите poll()
если вам нужны все записи с самого начала. Это немного хаккей, но, похоже, это самый надежный способ сделать это с версии 0.9.
// At this point, there is no heartbeat from consumer so seekToBeinning() wont work
// So call poll()
consumer.poll(0);
// Now there is heartbeat and consumer is "alive"
consumer.seekToBeginning(consumer.assignment());
// Now consume
ConsumerRecords<String, String> records = consumer.poll(0);
Ответ 3
Одним из возможных решений является использование реализации ConsumerRebalanceListener при подписке на одну или несколько тем. ConsumerRebalanceListener содержит методы обратного вызова, когда новые разделы назначаются или удаляются из потребителя. Следующий пример кода иллюстрирует это:
public class SkillsConsumer {
private String topic;
private KafkaConsumer<String, String> consumer;
private static final int POLL_TIMEOUT = 5000;
public SkillsConsumer(String topic) {
this.topic = topic;
Properties properties = ConsumerUtil.getConsumerProperties();
properties.put("group.id", "consumer-skills");
this.consumer = new KafkaConsumer<>(properties);
this.consumer.subscribe(Collections.singletonList(this.topic),
new PartitionOffsetAssignerListener(this.consumer));
}
}
public class PartitionOffsetAssignerListener implements ConsumerRebalanceListener {
private KafkaConsumer consumer;
public PartitionOffsetAssignerListener(KafkaConsumer kafkaConsumer) {
this.consumer = kafkaConsumer;
}
@Override
public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
}
@Override
public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
//reading all partitions from the beginning
for(TopicPartition partition : partitions)
consumer.seekToBeginning(partition);
}
}
Теперь, когда разделы назначаются потребителю, каждый раздел будет читаться с самого начала.
Ответ 4
1) fooobar.com/questions/194058/...
2) http://mail-archives.apache.org/mod_mbox/kafka-users/201403.mbox/%[email protected].com%3E
Чтобы сбросить группу потребителей, вы можете удалить идентификатор группы Zookeeper
import kafka.utils.ZkUtils;
ZkUtils.maybeDeletePath(<zkhost:zkport>, </consumers/group.id>);'
Ответ 5
при использовании пользовательского набора High Level props.put("auto.offset.reset", "smallest");
во время создания ConsumerConfig
Ответ 6
Если вы используете java-потребитель api более конкретно org.apache.kafka.clients.consumer.Consumer, вы можете попробовать методы поиска *.
consumer.seekToBeginning(consumer.assignment())
Здесь customer.assignment() возвращает все разделы, назначенные данному потребителю, и seekToBeginning начнет с самого раннего смещения для данного набора разделов.
Ответ 7
Так что для меня то, что сработало, было комбинацией того, что было предложено выше. Ключевое изменение должно было включать
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
и иметь случайно сгенерированный идентификатор группы каждый раз. Но это само по себе не сработало. По какой-то причине, когда я впервые опросил потребителя, он никогда не получал никаких записей. Мне пришлось взломать его, чтобы заставить его работать -
consumer.poll(0); // without this the below statement never got any records
final ConsumerRecords<Long, String> consumerRecords = consumer.poll(Duration.ofMillis(100));
Я новичок в KAFKA и не знаю, почему это происходит, но для всех, кто еще пытается заставить это работать, надеюсь, это поможет.
Ответ 8
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
Если вы просто избегаете сохранения каких-либо смещений, потребитель всегда будет сбрасываться в начале.