web-dev-qa-db-fra.com

CommitFailedException La validation ne peut pas être effectuée car le groupe a déjà rééquilibré et affecté les partitions à un autre membre

J'utilisais kafka 0.10.2 et maintenant face à une CommitFailedException. Comme:

La validation ne peut pas être effectuée car le groupe a déjà rééquilibré et affecté les partitions à un autre membre. Cela signifie que le temps entre les appels suivants à poll () était plus long que la valeur max.poll.interval.ms configurée, ce qui implique généralement que la boucle d'interrogation passe trop de temps à traiter les messages. Vous pouvez résoudre ce problème en augmentant le délai d'expiration de la session ou en réduisant la taille maximale des lots renvoyés dans poll () avec max.poll.records.

J'ai défini max.poll.interval.ms sur Integer.MAX_VALUE. alors quelqu'un peut-il me dire pourquoi cela se produit même si j'ai défini la valeur?

Une autre question est: je fais comme description pour définir session.timeout.ms à 60000 et cela se produit toujours. J'essaye de reproduire par un simple code

 public static void main(String[] args) throws InterruptedException {     
        Logger logger = Logger.getLogger(KafkaConsumer10.class);
        logger.info("XX");
        Properties props = new Properties();
        props.put("bootstrap.servers", "kafka-broker:9098");
        props.put("group.id", "test");
        props.put("enable.auto.commit", "true");
        props.put("auto.commit.interval.ms", "1000");
        props.put("key.deserializer", "org.Apache.kafka.common.serialization.StringDeserializer");
        props.put("value.deserializer", "org.Apache.kafka.common.serialization.StringDeserializer");
        props.put("max.poll.interval.ms", "300000");
        props.put("session.timeout.ms", "10000");
        props.put("max.poll.records", "2");
        KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
        consumer.subscribe(Arrays.asList("t1"));
        while (true) {
            Thread.sleep(11000);
            ConsumerRecords<String, String> records = consumer.poll(100);
            //Thread.sleep(11000);
            Thread.sleep(11000);
            for (ConsumerRecord<String, String> record : records)
                System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
        }

lorsque je mets session.timeout.ms à 10000, j'essaie de dormir plus de 10000 ms dans ma boucle d'interrogation, mais cela semble fonctionner sans aucune exception. donc je suis confus à ce sujet. si le rythme cardiaque est déclenché par consumer.poll et consumer.commit, il semble que le rythme cardiaque soit hors délai d'expiration de session dans mon code. pourquoi ne pas lancer CommitFailedException?

17
Simon Su

Salut Pour cela, vous devez gérer la condition de rééquilibrage dans votre code et devez traiter le message en cours et le valider avant le rééquilibrage

Comme :

private class HandleRebalance implements ConsumerRebalanceListener {
        public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
            // Implement what you want to do once rebalancing is done.
        }

        public void onPartitionsRevoked(Collection<TopicPartition> partitions) {

           // commit current method

       }
    }

et utilisez cette syntaxe pour vous abonner au sujet:

kafkaConsumer.subscribe (topicNameList, new HandleRebalance ())

L'avantage de faire ceci:

  1. Les messages ne se répéteront pas lors du rééquilibrage.

  2. Aucune exception d'échec de validation n'a conduit l'exception

5
Abhimanyu

session.timeout.ms défini sur le consommateur doit être inférieur au group.max.session.timeout.ms activé Kafka broker.

Cela a résolu le problème pour moi.

Crédit au lien github Commit Failures

3
Rahul Teke