Hystrixと既存のSpringアプリケーションとの統合

1.概要

リンク:/Introduction-to-hystrix[最後の記事]では、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を統合する方法を示すために、このクライアントを例として使用します。

これを行うには、** invokeRemoteService が実行されたときに開始する Around アドバイスを定義します。

@Around("@annotation(com.baeldung.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 Logic

それでは、 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 コンポーネントの実装全体はhttps://github.com/eugenp/tutorials/blob/master/hystrix/src/main/java/com/baeldung/hystrix/HystrixAspect.java[ここ]に見ることができます。

2.4. @ HystrixCircuitBreaker で注釈を付ける

アスペクトが定義されたら、以下に示すようにクライアントメソッドに @ HystrixCircuitBreaker のアノテーションを付けることができ、アノテーションが付けられたメソッドを呼び出すたびにHystrixが呼び出されます。

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

以下の統合テストは、HystrixルートとHystrix以外のルートの違いを示します。

2.5. 統合をテストする

デモンストレーションの目的で、Hystrixを使用する方法と使用しない方法の2つのメソッド実行ルートを定義しました。

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.まとめ

異なる設定で行いたいリモートサービスコールごとに1つのアスペクトを作成できます。次の記事では、プロジェクトの最初からHystrixを統合することを見ていきます。

この記事のすべてのコードはhttps://github.com/eugenp/tutorials/tree/master/hystrix[GitHub]リポジトリにあります。