web-dev-qa-db-fra.com

Obtenir une exception d'échec dans la méthode de secours @HystrixCommand

Existe-t-il un moyen d'obtenir la raison pour laquelle une variable HystrixCommand a échoué lors de l'utilisation de l'annotation @HystrixCommand dans une application Spring Boot? Il semble que si vous implémentez votre propre HystrixCommand, vous avez accès à la getFailedExecutionException mais comment pouvez-vous y avoir accès en utilisant l'annotation? J'aimerais pouvoir faire différentes choses dans la méthode de secours en fonction du type d'exception survenue. Est-ce possible?

J'ai vu une note à propos de HystrixRequestContext.initializeContext() mais la HystrixRequestContext ne vous donne accès à rien, existe-t-il une manière différente d'utiliser ce contexte pour accéder aux exceptions?

12
Andrew Serff

Je n'ai pas trouvé non plus de moyen d'obtenir l'exception avec Annotations, mais créer ma propre commande a fonctionné de la manière suivante:

public static class DemoCommand extends HystrixCommand<String> {

    protected DemoCommand() {
        super(HystrixCommandGroupKey.Factory.asKey("Demo"));
    }

    @Override
    protected String run() throws Exception {
        throw new RuntimeException("failed!");
    }

    @Override
    protected String getFallback() {
        System.out.println("Events (so far) in Fallback: " + getExecutionEvents());
        return getFailedExecutionException().getMessage();
    }

}

Espérons que cela aide aussi quelqu'un d'autre. 

11
Andrew Serff

Ajoutez simplement un paramètre Throwable à la méthode de repli et il recevra l'exception que la commande d'origine a produite.

De https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica

    @HystrixCommand(fallbackMethod = "fallback1")
    User getUserById(String id) {
        throw new RuntimeException("getUserById command failed");
    }

    @HystrixCommand(fallbackMethod = "fallback2")
    User fallback1(String id, Throwable e) {
        assert "getUserById command failed".equals(e.getMessage());
        throw new RuntimeException("fallback1 failed");
    }
40
MattJ

Je ne pouvais pas trouver un moyen d'obtenir l'exception avec les annotations, mais j'ai trouvé HystrixPlugins, avec lequel vous pouvez enregistrer une HystrixCommandExecutionHook et vous pouvez obtenir l'exception exacte comme suit: 

HystrixPlugins.getInstance().registerCommandExecutionHook(new HystrixCommandExecutionHook() {
            @Override
            public <T> void onFallbackStart(final HystrixInvokable<T> commandInstance) {

            }
        });

L'instance de commande est une GenericCommand.

2
Ákos Ratku

Comme indiqué dans la documentation, la méthode documentation HystrixgetFallback() sera émise lorsque:

  1. Chaque fois que l'exécution d'une commande échoue: lorsqu'une exception est levée par construct () ou run () 
  2. Lorsque la commande est court-circuitée car le circuit est ouvert 
  3. Lorsque le pool de threads et la file d'attente ou le sémaphore de la commande sont saturés 
  4. Lorsque la commande a dépassé son délai d'expiration.

Ainsi, vous pouvez facilement obtenir le nom de votre méthode de secours appelée en affectant l'exception d'exécution à un objet Throwable.

En supposant que votre HystrixCommand retourne une chaîne

public class ExampleTask extends HystrixCommand<String> {
   //Your class body
}

faire comme suit:

@Override
    protected ErrorCodes getFallback() {
        Throwable t = getExecutionException();
        if (circuitBreaker.isOpen()) {
            // Log or something
        } else if (t instanceof RejectedExecutionException) {
            // Log and get the threadpool name, could be useful
        } else {
            // Maybe something else happened
        }
        return "A default String"; // Avoid using any HTTP request or ypu will need to wrap it also in HystrixCommand
    }

Plus d'infos ici

1
vicco

La plupart du temps, juste en utilisant getFailedExecutionException (). GetMessage () m'a donné des valeurs null 

   Exception errorFromThrowable = getExceptionFromThrowable(getExecutionException());
   String errMessage = (errorFromThrowable != null) ? errorFromThrowable.getMessage()

cela me donne de meilleurs résultats tout le temps.

1
Seetharamani Tmr