1. 概述
在上一篇文章中,我們探討了 Hystrix 的基本原理以及它如何幫助構建容錯和彈性應用程序。
許多現有的 Spring 應用程序會調用外部系統,這些系統可以通過 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.baeldung.hystrix.HystrixCircuitBreaker)")
public Object circuitBreakerAround(ProceedingJoinPoint aJoinPoint) {
return new RemoteServiceCommand(config, aJoinPoint).execute();
}上述建議旨在作為 Around 建議,在帶有 @HystrixCircuitBreaker 註解的點切上執行。
現在讓我們來查看 HystrixCircuitBreaker 註解的定義:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HystrixCircuitBreaker {}2.3. 熔斷器邏輯
現在我們來查看 RemoteServiceCommand。它作為樣代碼中的一個 靜態內部類實現,以便封裝熔斷器調用邏輯:
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</em/> 註解
一旦切面已定義,就可以使用 @HystrixCircuitBreaker</em/> 註解來標記客户端方法,如以下示例所示。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 路由的方法會在定義的超時時間(在本例中為 10 秒)內短路並拋出 HystrixRuntimeException。
3. 結論
我們可以為每個遠程服務調用創建不同的方面,以便使用不同的配置進行交互。在下一篇文章中,我們將探討如何從項目的開端開始集成 Hystrix。