Перейти к основному содержимому

Интеграция Hystrix с существующим приложением Spring

· 3 мин. чтения

1. Обзор

В прошлой статье мы рассмотрели основы Hystrix и то, как он может помочь в создании отказоустойчивого и отказоустойчивого приложения.

Существует множество существующих приложений Spring, которые делают вызовы к внешним системам, которые выиграют от Hystrix. К сожалению, может оказаться невозможным переписать эти приложения для интеграции Hystrix, однако возможен неинвазивный способ интеграции Hystrix с помощью Spring AOP .

В этой статье мы рассмотрим, как интегрировать 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, мы будем использовать этот клиент в качестве примера.

Для этого мы определим совет Around , который сработает, когда будет выполнен invokeRemoteService :

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

Вышеупомянутый совет разработан как совет Around , который должен выполняться в pointcut, аннотированном @HystrixCircuitBreaker .

Теперь посмотрим определение аннотации HystrixCircuitBreaker :

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

2.3. Логика Хайстрикс

Теперь давайте посмотрим на 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);
}
}
}

Всю реализацию компонента Aspect можно увидеть здесь .

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 секунд.

3. Заключение

Мы можем создать один аспект для каждого вызова удаленной службы, который мы хотим сделать с различными конфигурациями. В следующей статье мы рассмотрим интеграцию Hystrix с самого начала проекта.

Весь код в этой статье можно найти в репозитории GitHub .