Contents

Hystrix与Spring应用程序集成

1. 概述

在上一篇文章 中,我们了解了 Hystrix 的基础知识以及它如何帮助构建容错和弹性的应用程序。

**有许多现有的 Spring 应用程序可以调用将从 Hystrix 中受益的外部系统。**不幸的是,可能无法重写这些应用程序以集成 Hystrix,但是在Spring AOP 的帮助下,可以使用一种非侵入性的方式集成 Hystrix 。 在本文中,我们将了解如何将 Hystrix 与现有的 Spring 应用程序集成。

2. Hystrix 集成 Spring 应用

2.1. 现有应用程序

让我们看一下应用程序现有的客户端调用者,它调用我们在上一篇文章中创建的RemoteServiceTestSimulator

@Component("springClient")
public class SpringExistingClient {
    @Value("${remoteservice.timeout}")
    private int remoteServiceDelay;
    public String invokeRemoteServiceWithOutHystrix() throws InterruptedException {
        return new RemoteServiceTestSimulator(remoteServiceDelay).execute();
    }
}

正如我们在上面的代码片段中看到的,invokeRemoteServiceWithOutHystrix方法负责调用RemoteServiceTestSimulator远程服务。当然,一个现实世界的应用程序不会这么简单。

2.2. 创建一个周围的建议

为了演示如何集成 Hystrix,我们将使用这个客户端作为示例。

为此,我们将定义一个在invokeRemoteService被执行时将启动的Around建议

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

上述建议被设计为在使用*@HystrixCircuitBreaker注解的切入点处执行的Around*建议。

现在让我们看看HystrixCircuitBreaker注解的定义:

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

2.3. Hystrix 逻辑

现在让我们看一下RemoteServiceCommand。在示例代码中实现为静态内部类,从而封装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);
        }
    }
}

2.4. 使用*@HystrixCircuitBreaker* 进行注解

一旦定义了方面,我们可以使用*@HystrixCircuitBreaker*注解我们的客户端方法,如下所示,并且每次调用注解的方法都会触发Hystrix:

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

下面的集成测试将演示 Hystrix 路由和非 Hystrix 路由之间的区别。

2.5. 测试集成

出于演示的目的,我们定义了两种方法执行路线,一种使用 Hystrix,另一种没有。

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"));
    }
}

当测试执行时,您可以看到没有 Hystrix 的方法调用将等待远程服务的整个执行时间,而 Hystrix 路由将短路并在定义的超时后抛出HystrixRuntimeException,在我们的例子中是 10 秒。