J'utilise Spring Kafka pour la première fois et je ne parviens pas à utiliser la méthode Acknowledgement.acknowledge () pour la validation manuelle dans mon code client. s'il vous plaît laissez-moi savoir si quelque chose manque dans ma configuration consommateur ou code auditeur. ou bien existe-t-il un autre moyen de gérer le décalage d'acquittement en fonction de la condition . Ici, je cherche une solution comme si le décalage n’est pas validé/acquitté manuellement, il devrait choisir le même message/le même décalage par consommateur.
import Java.util.HashMap;
import Java.util.Map;
import org.Apache.kafka.clients.consumer.ConsumerConfig;
import org.Apache.kafka.common.serialization.StringDeserializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.listener.AbstractMessageListenerContainer.AckMode;
@EnableKafka
@Configuration
public class ConsumerConfig {
@Value(value = "${kafka.bootstrapAddress}")
private String bootstrapAddress;
@Value(value = "${kafka.groupId}")
private String groupId;
@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> containerFactory() {
Map<String, Object> props = new HashMap<String, Object>();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress);
props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, 100);
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
StringDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
StringDeserializer.class);
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");
ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<String, String>();
factory.setConsumerFactory(new DefaultKafkaConsumerFactory<String, String>(
props));
factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);
factory.getContainerProperties().setSyncCommits(true);
return factory;
}
}
------------------------
private static int value = 1;
@KafkaListener(id = "baz", topics = "${message.topic.name}", containerFactory = "containerFactory")
public void listenPEN_RE(@Payload String message,
@Header(KafkaHeaders.RECEIVED_PARTITION_ID) int partition,
@Header(KafkaHeaders.OFFSET) int offsets,
Acknowledgment acknowledgment) {
if (value%2==0){
acknowledgment.acknowledge();
}
value++;
}
Définissez la propriété enable-auto-commit sur false:
propsMap.put (ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
Définissez le mode ack sur MANUAL_IMMEDIATE:
factory.getContainerProperties (). setAckMode (AbstractMessageListenerContainer.AckMode.MANUAL_IMMEDIE)
Ensuite, dans votre code consommateur/auditeur, vous pouvez valider le décalage manuellement, comme ceci:
@KafkaListener(topics = "testKafka")
public void receive(ConsumerRecord<?, ?> consumerRecord,
Acknowledgment acknowledgment) {
System.out.println("Received message: ");
System.out.println(consumerRecord.value().toString());
acknowledgment.acknowledge();
}
Mise à jour: j'ai créé un petit POC pour cela. Check it out here , pourrait vous aider.
Cela ne fonctionne pas de cette façon dans Apache Kafka.
Pour le consommateur courant, nous ne pouvons jamais nous soucier de commettre des compensations. Nous avons besoin qu'ils ne persistent que pour les nouveaux consommateurs du même groupe de consommateurs. Le courant suit son décalage dans la mémoire. Je suppose que quelque part sur Broker.
Si vous devez récupérer le même message dans le même consommateur, peut-être lors du prochain tour de scrutin, vous devez envisager d'utiliser la fonctionnalité seek()
: https://docs.spring.io/spring-kafka/docs/2.0.1.RELEASE/ reference/html/_reference.html # cherche
Vous pouvez faire ce qui suit:
1. stocker le décalage de l'enregistrement en cours dans un fichier ou une base de données.
2. Implémentez votre classe d'écoute kafka avec ConsumerAware.
3. Appelez registerSeekCallback comme indiqué ci-dessous:
(registerSeekCallback(ConsumerSeekCallback callback)
{
callback.seek(topic, partition, offset)
}
Ainsi, lorsque le consommateur tombe en panne ou qu'un nouveau consommateur est affecté, il commence à lire le décalage stocké dans votre base de données.