web-dev-qa-db-ja.com

@HystrixCommandフォールバックメソッドで失敗例外を取得する

Spring Bootアプリケーション内で_@HystrixCommand_注釈を使用しているときにHystrixCommandが失敗した理由を取得する方法はありますか?独自のHystrixCommandを実装するとgetFailedExecutionExceptionにアクセスできるように見えますが、アノテーションを使用するときにこれにアクセスするにはどうすればよいですか?発生した例外の種類に基づいて、フォールバックメソッドで異なる処理を実行できるようにしたいと思います。これは可能ですか?

about HystrixRequestContext.initializeContext()を見ましたが、HystrixRequestContextは何にもアクセスできません。そのコンテキストを使用して、例外?

15
Andrew Serff

アノテーションで例外を取得する方法も見つけられませんでしたが、独自のコマンドを作成すると次のように機能しました:

public static class DemoCommand extends HystrixCommand<String> {

    protected DemoCommand() {
        super(HystrixCommandGroupKey.Factory.asKey("Demo"));
    }

    @Override
    protected String run() throws Exception {
        throw new RuntimeException("failed!");
    }

    @Override
    protected String getFallback() {
        System.out.println("Events (so far) in Fallback: " + getExecutionEvents());
        return getFailedExecutionException().getMessage();
    }

}

これが他の人にも役立つことを願っています。

12
Andrew Serff

フォールバックメソッドにThrowableパラメーターを追加するだけで、元のコマンドが生成した例外を受け取ります。

から https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica

    @HystrixCommand(fallbackMethod = "fallback1")
    User getUserById(String id) {
        throw new RuntimeException("getUserById command failed");
    }

    @HystrixCommand(fallbackMethod = "fallback2")
    User fallback1(String id, Throwable e) {
        assert "getUserById command failed".equals(e.getMessage());
        throw new RuntimeException("fallback1 failed");
    }
45
MattJ

私は注釈で例外を取得する方法を見つけることができませんでしたが、HystrixPluginsを見つけました。これにより、HystrixCommandExecutionHookを登録でき、そのように正確な例外を取得できます:

HystrixPlugins.getInstance().registerCommandExecutionHook(new HystrixCommandExecutionHook() {
            @Override
            public <T> void onFallbackStart(final HystrixInvokable<T> commandInstance) {

            }
        });

コマンドインスタンスはGenericCommandです。

2
Ákos Ratku

ドキュメントで述べたように Hystrix-documentationgetFallback()メソッドは次の場合にスローされます:

  1. コマンドの実行が失敗したときはいつでも、construct()またはrun()によって例外がスローされたとき
  2. 回路が開いているためにコマンドが短絡したとき
  3. コマンドのスレッドプールとキューまたはセマフォがいっぱいになったとき
  4. コマンドがタイムアウトの長さを超えたとき。

そのため、実行例外をThrowable objectに割り当てることで、フォールバックメソッドを呼び出したものを簡単に取得できます。

HystrixCommandが文字列を返すと仮定します

public class ExampleTask extends HystrixCommand<String> {
   //Your class body
}

次のようにします。

@Override
    protected ErrorCodes getFallback() {
        Throwable t = getExecutionException();
        if (circuitBreaker.isOpen()) {
            // Log or something
        } else if (t instanceof RejectedExecutionException) {
            // Log and get the threadpool name, could be useful
        } else {
            // Maybe something else happened
        }
        return "A default String"; // Avoid using any HTTP request or ypu will need to wrap it also in HystrixCommand
    }

詳細 こちら

1
vicco

ほとんどの場合、単にgetFailedExecutionException()。getMessage()を使用すると、null値が返されます。

   Exception errorFromThrowable = getExceptionFromThrowable(getExecutionException());
   String errMessage = (errorFromThrowable != null) ? errorFromThrowable.getMessage()

これにより、常により良い結果が得られます。

1