【问题标题】:Get failure exception in @HystrixCommand fallback method在@HystrixCommand 回退方法中获取失败异常
【发布时间】:2015-12-26 03:32:23
【问题描述】:

在 Spring Boot 应用程序中使用 @HystrixCommand 注释时,有没有办法获取 HystrixCommand 失败的原因?看起来如果您实现自己的HystrixCommand,您可以访问getFailedExecutionException,但是在使用注释时如何访问它?我希望能够根据发生的异常类型在回退方法中做不同的事情。这可能吗?

我看到了一个关于 HystrixRequestContext.initializeContext()note,但 HystrixRequestContext 不能让您访问任何内容,是否有其他方法可以使用该上下文来访问异常?

【问题讨论】:

    标签: spring spring-cloud hystrix


    【解决方案1】:

    只需在回退方法中添加一个 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");
        }
    

    【讨论】:

    • 对于Throwable e,它可以告诉我真正的原因,例如FAILURE/SHORTCIRCUITED/TIMEOUT/BAD_REQUEST/SEMAPHORE_REJECTED/THREAD_POOL_REJECTED。有人说他们不能,因为他们需要调整 javanica 以使用 getExecutionException() 而不是 @vicco 提到的 getFailedExecutionException()。
    【解决方案2】:

    我也没有找到使用注释获取异常的方法,但是创建我自己的命令对我很有效:

    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();
        }
    
    }
    

    希望这对其他人也有帮助。

    【讨论】:

      【解决方案3】:

      正如文档中所说的Hystrix-documentation getFallback() 方法将在以下情况下被抛出:

      1. 当命令执行失败时:当construct()或run()抛出异常时
      2. 当命令因为电路开路而短路时
      3. 当命令的线程池和队列或信号量满时
      4. 当命令超过其超时长度时。

      因此,您可以通过将执行异常分配给 Throwable 对象,轻松获取引发您调用的回退方法的原因。

      假设你的 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
          }
      

      更多信息here

      【讨论】:

        【解决方案4】:

        我找不到通过注释获取异常的方法,但我找到了HystrixPlugins,你可以注册一个HystrixCommandExecutionHook,你可以像这样得到确切的异常:

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

        命令实例是GenericCommand

        【讨论】:

        • 但这通常会在每次执行命令时捕获它们,并且不会与特定的命令执行相关联,对吗?不完全是我所追求的,但在您需要了解失败的某些情况下仍然可能会有所帮助。
        【解决方案5】:

        大多数时候只是使用 getFailedExecutionException().getMessage() 给了我空值。

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

        这总是给我更好的结果。

        【讨论】:

          猜你喜欢
          • 2019-05-27
          • 1970-01-01
          • 2017-12-30
          • 2018-09-23
          • 1970-01-01
          • 2014-07-29
          • 1970-01-01
          • 2018-10-23
          • 1970-01-01
          相关资源
          最近更新 更多