J'utilise actuellement Spring Integration Kafka pour établir des statistiques en temps réel. Cependant, le nom du groupe fait rechercher par Kafka toutes les valeurs précédentes que l'auditeur n'a pas lues.
@Value("${kafka.consumer.group.id}")
private String consumerGroupId;
@Bean
public ConsumerFactory<String, String> consumerFactory() {
return new DefaultKafkaConsumerFactory<>(getDefaultProperties());
}
public Map<String, Object> getDefaultProperties() {
Map<String, Object> properties = new HashMap<>();
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
properties.put(ConsumerConfig.GROUP_ID_CONFIG, consumerGroupId);
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class);
return properties;
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
return factory;
}
@Bean
public KafkaMessageListener listener() {
return new KafkaMessageListener();
}
Je voudrais commencer avec le dernier décalage et ne pas être dérangé par les anciennes valeurs. Existe-t-il une possibilité de réinitialiser le décalage du groupe?
Parce que je n'ai vu aucun exemple de cela, je vais expliquer comment je l'ai fait ici.
La classe de votre @KafkaListener
doit implémenter une classe ConsumerSeekAware
, qui permettra à l’auditeur de contrôler la recherche de décalage lorsque des partitions sont attribuées. (source: https://docs.spring.io/spring-kafka/reference/htmlsingle/#seek )
public class KafkaMessageListener implements ConsumerSeekAware {
@KafkaListener(topics = "your.topic")
public void listen(byte[] payload) {
// ...
}
@Override
public void registerSeekCallback(ConsumerSeekCallback callback) {
}
@Override
public void onPartitionsAssigned(Map<TopicPartition, Long> assignments, ConsumerSeekCallback callback) {
assignments.forEach((t, o) -> callback.seekToEnd(t.topic(), t.partition()));
}
@Override
public void onIdleContainer(Map<TopicPartition, Long> assignments, ConsumerSeekCallback callback) {
}
}
Ici, lors d'un rééquilibrage, nous utilisons le rappel donné pour rechercher le dernier décalage pour tous les sujets donnés. Merci à Artem Bilan ( https://stackoverflow.com/users/2756547/artem-bilan ) de m'avoir guidé vers la réponse.
On dirait que vous devez vous soucier du auto.offset.reset
du consommateur. Mais ce qui me rend confus que c’est quand même latest
:
auto.offset.reset What to do when there is no initial offset in Kafka or if the current offset does not exist any more on the server (e.g. because that data has been deleted):
earliest: automatically reset the offset to the earliest offset
latest: automatically reset the offset to the latest offset
none: throw exception to the consumer if no previous offset is found for the consumer's group
anything else: throw exception to the consumer.
string latest [latest, earliest, none] medium
Vous pouvez définir une variable ConsumerRebalanceListener
pour le consommateur kafka lors de votre abonnement à certaines rubriques, dans laquelle vous pouvez obtenir le dernier décalage de chaque partition par la méthode KafkaConsumer.endOffsets()
et définir ceci en consommateur par la méthode KafkaConsumer.seek()
, comme ceci:
kafkaConsumer.subscribe(Collections.singletonList(topics),
new ConsumerRebalanceListener() {
@Override
public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
//do nothing
}
@Override
public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
//get and set the lastest offset for each partiton
kafkaConsumer.endOffsets(partitions)
.forEach((partition, offset) -> kafkaConsumer.seek(partition, offset));
}
}
);
vous pouvez utiliser l'annotation partitionOffsets pour commencer avec le décalage exact, par exemple:
@KafkaListener(id = "bar", topicPartitions =
{ @TopicPartition(topic = "topic1", partitions = { "0", "1" }),
@TopicPartition(topic = "topic2", partitions = "0",
partitionOffsets = @PartitionOffset(partition = "1", initialOffset = "100"))
})public void listen(ConsumerRecord<?, ?> record) {
}