Intégration Hystrix avec une application Spring existante

1. Vue d’ensemble

Dans le dernier article , nous avons examiné les bases d’Hystrix et comment il peut contribuer à la création d’une application tolérante aux pannes et résistante.

  • De nombreuses applications Spring existantes appelant des systèmes externes pourraient tirer profit d’Hystrix. ** Malheureusement, il n’est peut-être pas possible de réécrire ces applications pour intégrer Hystrix. Toutefois, une méthode non invasive d’intégration de Hystrix est possible l’aide de Spring AOP .

Dans cet article, nous verrons comment intégrer Hystrix à une application Spring existante.

2. Hystrix dans une application Spring

2.1. Application existante

Jetons un coup d’œil à l’appelant client existant de l’application qui appelle la fonction RemoteServiceTestSimulator que nous avons créée dans l’article précédent:

@Component("springClient")
public class SpringExistingClient {

    @Value("${remoteservice.timeout}")
    private int remoteServiceDelay;

    public String invokeRemoteServiceWithOutHystrix() throws InterruptedException {
        return new RemoteServiceTestSimulator(remoteServiceDelay).execute();
    }
}

Comme nous pouvons le voir dans l’extrait de code ci-dessus, la méthode invokeRemoteServiceWithOutHystrix est responsable de l’appel au service distant RemoteServiceTestSimulator . Bien sûr, les applications du monde réel ne seront pas aussi simples.

2.2. Créer un conseil autour

Pour montrer comment intégrer Hystrix, nous allons utiliser ce client à titre d’exemple.

Pour ce faire, nous définirons un conseil Around qui sera activé lorsque invokeRemoteService sera exécuté :

@Around("@annotation(com.baeldung.hystrix.HystrixCircuitBreaker)")
public Object circuitBreakerAround(ProceedingJoinPoint aJoinPoint) {
    return new RemoteServiceCommand(config, aJoinPoint).execute();
}

Le conseil ci-dessus est conçu comme un conseil Around à exécuter à un point coupé annoté avec @ HystrixCircuitBreaker .

Voyons maintenant la définition de l’annotation HystrixCircuitBreaker _: _

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HystrixCircuitBreaker {}

2.3. La logique Hystrix

Voyons maintenant la RemoteServiceCommand . Il est implémenté en tant que static inner class dans l’exemple de code, de manière à encapsuler la logique d’appel Hystrix:

private static class RemoteServiceCommand extends HystrixCommand<String> {

    private ProceedingJoinPoint joinPoint;

    RemoteServiceCommand(Setter config, ProceedingJoinPoint joinPoint) {
        super(config);
        this.joinPoint = joinPoint;
    }

    @Override
    protected String run() throws Exception {
        try {
            return (String) joinPoint.proceed();
        } catch (Throwable th) {
            throw new Exception(th);
        }
    }
}

L’ensemble de l’implémentation du composant Aspect est visible à l’adresse here .

2.4. Annoter avec @ HystrixCircuitBreaker

Une fois que l’aspect est défini, nous pouvons annoter notre méthode client avec @ HystrixCircuitBreaker comme indiqué ci-dessous et Hystrix sera provoqué à chaque appel de méthodes annotées:

@HystrixCircuitBreaker
public String invokeRemoteServiceWithHystrix() throws InterruptedException{
    return new RemoteServiceTestSimulator(remoteServiceDelay).execute();
}

Le test d’intégration ci-dessous démontrera la différence entre la route Hystrix et la route non Hystrix.

2.5. Tester l’intégration

À des fins de démonstration, nous avons défini deux itinéraires d’exécution de méthodes, l’un avec Hystrix et l’autre sans.

public class SpringAndHystrixIntegrationTest {

    @Autowired
    private HystrixController hystrixController;

    @Test(expected = HystrixRuntimeException.class)
    public void givenTimeOutOf15000__whenClientCalledWithHystrix__thenExpectHystrixRuntimeException()
      throws InterruptedException {
        hystrixController.withHystrix();
    }

    @Test
    public void givenTimeOutOf15000__whenClientCalledWithOutHystrix__thenExpectSuccess()
      throws InterruptedException {
        assertThat(hystrixController.withOutHystrix(), equalTo("Success"));
    }
}

Lorsque le test s’exécute, vous pouvez constater que l’appel à la méthode sans Hystrix attendra la durée d’exécution complète du service distant, tandis que la route Hystrix court-circuitera et lèvera la HystrixRuntimeException après le délai d’expiration défini, qui est dans notre cas de 10 secondes.

3. Conclusion

Nous pouvons créer un aspect pour chaque appel de service distant que nous souhaitons effectuer avec différentes configurations. Dans le prochain article, nous examinerons l’intégration de Hystrix dès le début d’un projet.

Tout le code de cet article se trouve dans le référentiel GitHub .