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 秒。