Feign 的两个调用处理器
feign 的调用处理器有默认的 FeignInvocationHandler
和 HystrixInvocationHandler,这篇文章我们将具体讲解一下这两个类
FeignInvocationHandler
Feign 远程调用的执行流程:调用 FeignInvocationHandler 的 invoke 方法
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("equals".equals(method.getName())) { try { Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null; return equals(otherHandler); } catch (IllegalArgumentException e) { return false; } } else if ("hashCode".equals(method.getName())) { return hashCode(); } else if ("toString".equals(method.getName())) { return toString(); } return dispatch.get(method).invoke(args); }
复制代码
这个方法中调用 SynchronousMethodHandler 方法处理器的 invoke 方法:dispatch.get(method).invoke(args);
SynchronousMethodHandler 的 invoke 方法中通过 RestTemplate 完成远程调用和获取调用的结果
FeignInvocationHandler 没有异常的熔断检测和恢复机制,也没有 Http 连接池。
HystrixInvocationHandler
HystrixInvocationHandler 的 invoke 方法创建 HystrixCommand 实例,HystrixCommand 的 getFallback()方法中调用 @FeignClient 注解中的 fallback 属性上指定的失败回退的类,执行业务回退的处理。
@Override protected Object getFallback() { if (fallbackFactory == null) { return super.getFallback(); } try { 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 { return result; } } catch (IllegalAccessException e) { // shouldn't happen as method is public due to being an interface throw new AssertionError(e); } catch (InvocationTargetException e) { // Exceptions on fallback are tossed by Hystrix throw new AssertionError(e.getCause()); } }
复制代码
Feign 的 JDK 动态代理实例是通过 Feign.Builder 的 target()方法完成,target 方法第一步是通过自身的 build()方法构造 RefectiveFeign 实例,然后调用 RefectiveFeign 的 newInstance()方法来创建真正的实例,对于 RefectiveFeign 的作用,我们上篇文章详细讲解了一下,这里就不再赘述了。
使用 HystrixFeign
在 FeignClientsConfiguration 类中我们可以看到 HystrixFeign 替代 feign.Feign 的条件
@Configuration @ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class }) protected static class HystrixFeignConfiguration { @Bean @Scope("prototype") @ConditionalOnMissingBean @ConditionalOnProperty(name = "feign.hystrix.enabled") public Feign.Builder feignHystrixBuilder() { return HystrixFeign.builder(); } }
复制代码
类路径中有 HystrixCommand 类和 HystrixFeign 类,并且配置文件中有 feign.hystrix.enabled,满足这两个条件后就可以用 HystrixFeign 替代原来的 Feign
总结
这篇文章主要介绍了 Feign 的两个调用处理器,FeignInvocationHandler 和 HystrixInvocationHandler,FeignInvocationHandler 调用处理器没有异常的熔断机制和恢复机制,HystrixInvocationHandler 调用处理支持熔断和异常处理,getFallback()处理调用失败的业务处理,另外可以通过配置文件来配置 feign.hystrix.enabled 让 HystrixFeign 进行替代 feign.Feign
评论