栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

com.netflix.hystrix.exception.HystrixRuntimeException: XxxClient#getXxx() failed and fallback failed

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

com.netflix.hystrix.exception.HystrixRuntimeException: XxxClient#getXxx() failed and fallback failed

异常:

│ com.netflix.hystrix.exception.HystrixRuntimeException: XxxClient#getXxx() failed and fallback failed.                                                                                  
│     at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:832)                                                                                                                              
│     at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:807)                                                                                                                              
│     at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140)                                                                                
│     at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)                                                                                                  
│     at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)                                                                                                  
│     at com.netflix.hystrix.AbstractCommand$DeprecatedOnFallbackHookApplication$1.onError(AbstractCommand.java:1472)                                                                                       
│     at com.netflix.hystrix.AbstractCommand$FallbackHookApplication$1.onError(AbstractCommand.java:1397)                                                                                                   
│     at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)                                                                                                  
│     at rx.observers.Subscribers$5.onError(Subscribers.java:230)                                                                                                                                           
│     at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:44)                                                                                                                              
│     at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:28)                                                                                                                              
│     at rx.Observable.unsafeSubscribe(Observable.java:10327)                                                                                                                                               
│     at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)                                                                                                                              
│     at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)                                                                                                                              
│     at rx.Observable.unsafeSubscribe(Observable.java:10327)                                                                                                                                               
│     at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)                                                                                                                        
│     at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)                                                                                                                        
│     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)                                                                                                                                
│     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)                                                                                                                                
│     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)                                                                                                                                
│     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)                                                                                                                                
│     at rx.Observable.unsafeSubscribe(Observable.java:10327)                                                                                                                                               
│     at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)                                                                                                                        
│     at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)                                                                                                                        
│     at rx.Observable.unsafeSubscribe(Observable.java:10327)                                                                                                                                               
│     at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)                                                                                                                        
│     at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)                                                                                                                        
│     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)                                                                                                                                
│     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)                                                                                                                                
│     at rx.Observable.unsafeSubscribe(Observable.java:10327)                                                                                                                                               
│     at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)                                                                                                                        
│     at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)                                                                                                                        
│     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)                                                                                                                                
│     at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)                                                                                                                                
│     at rx.Observable.unsafeSubscribe(Observable.java:10327)                                                                                                                                               
│     at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:142)                                                                                
│     at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)                                                                                                  
│     at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)                                                                                                  
│     at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$3.onError(AbstractCommand.java:1194)                                                                                          
│     at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.onError(OperatorSubscribeOn.java:80)                                                                                               
│     at rx.observers.Subscribers$5.onError(Subscribers.java:230)                                                                                                                                           
│     at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)                                                                                                  
│     at rx.observers.Subscribers$5.onError(Subscribers.java:230)                                                                                                                                           
│     at com.netflix.hystrix.AbstractCommand$DeprecatedOnRunHookApplication$1.onError(AbstractCommand.java:1431)                                                                                            
│     at com.netflix.hystrix.AbstractCommand$ExecutionHookApplication$1.onError(AbstractCommand.java:1362)     

问题产生:

通过spring openfeign的FallbackFactory对feign接口进行降级熔断操作;具体问题产生原因是FallbackFactory#create创建的对象,通过反射调用相关方法时,方法内部抛出了 Runtime Exception,也就是说并非降级操作不起作用,而是写的降级方法本身存在问题!比如 方法內抛出了异常、属性注入失败等等

OpenFeign提供的两种降级操作:

1、fallback

@FeignClient(name = "test", url = "http://localhost:${server.port}/", fallback = Fallback.class)
    protected interface TestClient {

        @RequestMapping(method = RequestMethod.GET, value = "/hello")
        Hello getHello();

        @RequestMapping(method = RequestMethod.GET, value = "/hellonotfound")
        String getException();

    }

    @Component
    static class Fallback implements TestClient {

        @Override
        public Hello getHello() {
            throw new NoFallbackAvailableException("Boom!", new RuntimeException());
        }

        @Override
        public String getException() {
            return "Fixed response";
        }

    }

这种方式最简单,当feign接口调用失败时直接走fallback方法,不足之处在于拿不到具体feign调用失败的err信息

2、fallbackFactory

@FeignClient(name = "testClientWithFactory", url = "http://localhost:${server.port}/",
            fallbackFactory = TestFallbackFactory.class)
    protected interface TestClientWithFactory {

        @RequestMapping(method = RequestMethod.GET, value = "/hello")
        Hello getHello();

        @RequestMapping(method = RequestMethod.GET, value = "/hellonotfound")
        String getException();

    }

    @Component
    static class TestFallbackFactory implements FallbackFactory {

        @Override
        public FallbackWithFactory create(Throwable cause) {
            return new FallbackWithFactory();
        }

    }

    static class FallbackWithFactory implements TestClientWithFactory {

        @Override
        public Hello getHello() {
            throw new NoFallbackAvailableException("Boom!", new RuntimeException());
        }

        @Override
        public String getException() {
            return "Fixed response";
        }
}

通过这种方式就可以在创建fallback实体对象的时候把throwable错误信息传回来

3、fallback与fallbackFactory的差别:
两者最终的处理方式都是一致的,fallbackFactory在真正使用的时候才创建需要的fallback对象,这个时候就很方便的将throwable信息传回;fallback最终也会使用默认的工厂方法:

  
  final class Default implements FallbackFactory {
    // jul to not add a dependency
    final Logger logger;
    final T constant;

    public Default(T constant) {
      this(constant, Logger.getLogger(Default.class.getName()));
    }

    Default(T constant, Logger logger) {
      this.constant = checkNotNull(constant, "fallback");
      this.logger = checkNotNull(logger, "logger");
    }

    @Override
    public T create(Throwable cause) {
      if (logger.isLoggable(Level.FINE)) {
        logger.log(Level.FINE, "fallback due to: " + cause.getMessage(), cause);
      }
      return constant;
    }

    @Override
    public String toString() {
      return constant.toString();
    }
  }

当然这个默认的工厂方法创建的fallback对象是没有携带throwable信息的

来看看两者最终都会调用fallback的方法:
feign.hystrix.HystrixInvocationHandler#invoke

  public Object invoke(final Object proxy, final Method method, final Object[] args)
      throws Throwable {

 .......

    HystrixCommand hystrixCommand =
        new HystrixCommand(setterMethodMap.get(method)) {
      .......

          @Override
          protected Object getFallback() {
            if (fallbackFactory == null) {
              return super.getFallback();
            }
            try {
            // 如果要走fallback的话,最终都就走到这里来
            // fallbackFactory要么是默认的,要么是自定义的,也就是对应的以上两种定义fallback的方式
              Object fallback = fallbackFactory.create(getExecutionException());
              Object result = fallbackMethodMap.get(method).invoke(fallback, args);
              if (isReturnsHystrixCommand(method)) {
                return ((HystrixCommand) result).execute();
              } else if (isReturnsObservable(method)) {
                // Create a cold Observable
                return ((Observable) result).toBlocking().first();
              } else if (isReturnsSingle(method)) {
                // Create a cold Observable as a Single
                return ((Single) result).toObservable().toBlocking().first();
              } else if (isReturnsCompletable(method)) {
                ((Completable) result).await();
                return null;
              } else if (isReturnsCompletableFuture(method)) {
                return ((Future) result).get();
              } else {
                return result;
              }
            } catch (IllegalAccessException e) {
              // shouldn't happen as method is public due to being an interface
              throw new AssertionError(e);
            } catch (InvocationTargetException | ExecutionException e) {
              // Exceptions on fallback are tossed by Hystrix
              throw new AssertionError(e.getCause());
            } catch (InterruptedException e) {
              // Exceptions on fallback are tossed by Hystrix
              Thread.currentThread().interrupt();
              throw new AssertionError(e.getCause());
            }
          }
        };

........

 



简单来说: 两种降级操作 fallback 和 fallbackFactory的处理方式是一致的,如果想要拿到具体的异常信息就使用 fallbackFactory


调试版本: org.springframework.cloud:spring-cloud-openfeign:2.2.5.RELEASE 以及其依赖的io.github.openfeign:feign-hystrix:10.10.1




以上是个人理解,如有问题请指出!

参考 spring-cloud-openfeign

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号