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
评论