0


feign的Fallback机制

对接口使用@FeignClient后声明feign客户端后,可以使用属性fallback指定异常处理类,这个类必须实现@FeignClient作用的接口,且被注入到容器中。

@FeignClient(name ="service-provider1",fallback =NacosFeignImpl.class)publicinterfaceNacosFeignClient{@RequestMapping(value ="/echo/{str}",method =RequestMethod.GET)Stringecho(@PathVariable("str")String str);}@ComponentpublicclassNacosFeignImplimplementsNacosFeignClient{@OverridepublicStringecho(String str){System.out.println("NacosFeignImpl#echo called");return"echo error";}}

添加配置项

feign.hystrix.enabled=true

,当配置了HystrixFeign时,即会创建HystrixFeign.Builder。

// FeignClientsConfiguration.java@Configuration@ConditionalOnClass({HystrixCommand.class,HystrixFeign.class})protectedstaticclassHystrixFeignConfiguration{@Bean@Scope("prototype")@ConditionalOnMissingBean@ConditionalOnProperty(name ="feign.hystrix.enabled")publicFeign.BuilderfeignHystrixBuilder(){returnHystrixFeign.builder();}}

在HystrixTargeter#target()发现使用了HystrixFeign.Builder并且属性fallback存在时,就会通过targetWithFallback()创建feign客户端。这里会到容器中获取实现了@FeignClient接口的Bean。

public<T>Ttarget(FeignClientFactoryBean factory,Feign.Builder feign,FeignContext context,Target.HardCodedTarget<T> target){if(!(feign instanceoffeign.hystrix.HystrixFeign.Builder)){return feign.target(target);}feign.hystrix.HystrixFeign.Builder builder =(feign.hystrix.HystrixFeign.Builder) feign;SetterFactory setterFactory =getOptional(factory.getName(), context,SetterFactory.class);if(setterFactory !=null){
            builder.setterFactory(setterFactory);}Class<?> fallback = factory.getFallback();if(fallback !=void.class){returntargetWithFallback(factory.getName(), context, target, builder, fallback);}Class<?> fallbackFactory = factory.getFallbackFactory();if(fallbackFactory !=void.class){returntargetWithFallbackFactory(factory.getName(), context, target, builder, fallbackFactory);}return feign.target(target);}

此时创建InvocationHandlerFactory,注入到属性invocationHandlerFactory,invocationHandlerFactory默认是

InvocationHandlerFactory.Default

,这里重写create()方法,创建了HystrixInvocationHandler的实例对象。

Feignbuild(finalFallbackFactory<?> nullableFallbackFactory){super.invocationHandlerFactory(newInvocationHandlerFactory(){@OverridepublicInvocationHandlercreate(Target target,Map<Method,MethodHandler> dispatch){returnnewHystrixInvocationHandler(target, dispatch, setterFactory, nullableFallbackFactory);}});super.contract(newHystrixDelegatingContract(contract));returnsuper.build();}

生成代理对象时,就会调用create()对HystrixInvocationHandler实例化,这样就会调用HystrixInvocationHandler#invoke()。

public<T>TnewInstance(Target<T> target){......InvocationHandler handler = factory.create(target, methodToHandler);T proxy =(T)Proxy.newProxyInstance(target.type().getClassLoader(),newClass<?>[]{target.type()}, handler);for(DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers){
      defaultMethodHandler.bindTo(proxy);}return proxy;}

invoke()中run()的逻辑还是调用SynchronousMethodHandler#invoke()处理请求,发生异常时就会到getFallback()调用接口的实现类对象的方法。

publicObjectinvoke(finalObject proxy,finalMethod method,finalObject[] args)throwsThrowable{// early exit if the invoked method is from java.lang.Object// code is the same as ReflectiveFeign.FeignInvocationHandlerif("equals".equals(method.getName())){try{Object otherHandler =
            args.length >0&& args[0]!=null?Proxy.getInvocationHandler(args[0]):null;returnequals(otherHandler);}catch(IllegalArgumentException e){returnfalse;}}elseif("hashCode".equals(method.getName())){returnhashCode();}elseif("toString".equals(method.getName())){returntoString();}HystrixCommand<Object> hystrixCommand =newHystrixCommand<Object>(setterMethodMap.get(method)){@OverrideprotectedObjectrun()throwsException{try{returnHystrixInvocationHandler.this.dispatch.get(method).invoke(args);}catch(Exception e){throw e;}catch(Throwable t){throw(Error) t;}}@OverrideprotectedObjectgetFallback(){if(fallbackFactory ==null){returnsuper.getFallback();}try{Object fallback = fallbackFactory.create(getExecutionException());Object result = fallbackMethodMap.get(method).invoke(fallback, args);if(isReturnsHystrixCommand(method)){return((HystrixCommand) result).execute();}elseif(isReturnsObservable(method)){// Create a cold Observablereturn((Observable) result).toBlocking().first();}elseif(isReturnsSingle(method)){// Create a cold Observable as a Singlereturn((Single) result).toObservable().toBlocking().first();}elseif(isReturnsCompletable(method)){((Completable) result).await();returnnull;}else{return result;}}catch(IllegalAccessException e){// shouldn't happen as method is public due to being an interfacethrownewAssertionError(e);}catch(InvocationTargetException e){// Exceptions on fallback are tossed by HystrixthrownewAssertionError(e.getCause());}}};if(isReturnsHystrixCommand(method)){return hystrixCommand;}elseif(isReturnsObservable(method)){// Create a cold Observablereturn hystrixCommand.toObservable();}elseif(isReturnsSingle(method)){// Create a cold Observable as a Singlereturn hystrixCommand.toObservable().toSingle();}elseif(isReturnsCompletable(method)){return hystrixCommand.toObservable().toCompletable();}return hystrixCommand.execute();}
标签: java spring cloud feign

本文转载自: https://blog.csdn.net/weixin_42145727/article/details/128875925
版权归原作者 葡萄晓虎 所有, 如有侵权,请联系我们删除。

“feign的Fallback机制”的评论:

还没有评论