web-dev-qa-db-fra.com

Gestion des exceptions dans les flux Kafka

Avait parcouru plusieurs publications, mais la plupart d'entre elles concernaient la gestion des mauvais messages et non la gestion des exceptions lors de leur traitement.

Je veux savoir comment gérer les messages reçus par l'application de flux et il y a une exception lors du traitement du message? L'exception peut être due à plusieurs raisons, comme une panne de réseau, RuntimeException etc.,

  • Quelqu'un pourrait-il suggérer la bonne façon de procéder? Dois-je utiliser setUncaughtExceptionHandler? ou existe-t-il une meilleure façon?
  • Comment gérer les nouvelles tentatives?

Merci d'avance!!

10
Thiru

cela dépend de ce que vous voulez faire avec les exceptions du côté des producteurs. si une exception est levée sur le producteur (par exemple en raison d'une défaillance du réseau ou kafka est mort), le flux mourra par défaut. et avec la version 1.1.0 de kafka-streams, vous pouvez remplacer le comportement par défaut en implémentant ProductionExceptionHandler comme suit:

public class CustomProductionExceptionHandler implements ProductionExceptionHandler {

    @Override
    public ProductionExceptionHandlerResponse handle(final ProducerRecord<byte[], byte[]> record,
                                                     final Exception exception) {
        log.error("Kafka message marked as processed although it failed. Message: [{}], destination topic: [{}]",  new String(record.value()), record.topic(), exception);
        return ProductionExceptionHandlerResponse.CONTINUE;
    }

    @Override
    public void configure(final Map<String, ?> configs) {
    }

}

à partir de la méthode handle, vous pouvez renvoyer soit CONTINUE si vous ne voulez pas que les flux meurent à l'exception, au retour FAIL au cas où vous voudriez que le flux s'arrête (FAIL est celui par défaut). et vous devez spécifier cette classe dans la configuration de flux:

default.production.exception.handler=com.example.CustomProductionExceptionHandler

Faites également attention que ProductionExceptionHandler ne gère que les exceptions sur le producteur, et il ne gérera pas les exceptions pendant le traitement du message avec les méthodes de flux mapValues(..), filter(..), branch(..) etc, vous devez encapsuler cette logique de méthode avec des blocs try/catch (mettez toute votre logique de méthode dans le bloc try pour garantir que vous gérerez tous les cas exceptionnels):

.filter((key, value) -> { try {..} catch (Exception e) {..} })

comme je le sais, nous n'avons pas besoin de gérer explicitement les exceptions côté consommateur, car kafka les flux réessayeront automatiquement de consommer plus tard (car l'offset ne sera pas modifié tant que les messages ne seront pas consommés et traités); par exemple, si kafka le courtier ne sera pas accessible pendant un certain temps, vous obtiendrez des exceptions de kafka streams, et quand il sera interrompu, kafka stream consommera tous les messages. dans ce cas, nous aurons juste du retard et rien de corrompu/perdu.

avec setUncaughtExceptionHandler, vous ne pourrez pas modifier le comportement par défaut comme avec ProductionExceptionHandler, avec lui, vous ne pourrez que consigner l'erreur ou envoyer un message dans la rubrique d'échec.

10
Vasiliy Sarzhynskyi

Pour gérer les exceptions côté consommateur,

1) Vous pouvez ajouter un gestionnaire d'exceptions par défaut dans le producteur avec la propriété suivante. "default.deserialization.exception.handler" = "org.Apache.kafka.streams.errors.LogAndContinueExceptionHandler";

Fondamentalement, Apache fournit trois classes de gestionnaire d'exceptions comme

1) LogAndContiuneExceptionHandler que vous pouvez prendre comme props.put (StreamsConfig.DEFAULT_DESERIALIZATION_EXCEPTION_HANDLER_CLASS_CONFIG, LogAndContinueExceptionHandler.class);

2) LogAndFailExceptionHandler props.put (StreamsConfig.DEFAULT_DESERIALIZATION_EXCEPTION_HANDLER_CLASS_CONFIG, LogAndFailExceptionHandler.class);

3) LogAndSkipOnInvalidTimestamp props.put (StreamsConfig.DEFAULT_DESERIALIZATION_EXCEPTION_HANDLER_CLASS_CONFIG, LogAndSkipOnInvalidTimestamp.class);

Pour la gestion des exceptions personnalisées,

1) vous pouvez implémenter l'interface DeserializationExceptionHandler et remplacer la méthode handle ().

2) Ou vous pouvez étendre les classes mentionnées ci-dessus.

4
Vishal Pawar