简介https://spring-cloud-wiki.readthedocs.io/zh_CN/latest/pages/feign.html
Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和注解,就可以定义好HTTP请求的参数、格式、地址等信息。Feign会完全代理HTTP请求,开发时只需要像调用方法一样调用它就可以完成服务请求及相关处理。
开源地址:https://github.com/OpenFeign/feign。Feign整合了Ribbon负载和Hystrix熔断,可以不再需要显式地使用这两个组件。总体来说,Feign具有如下特性:
- 可插拔的注解支持,包括Feign注解和JAX-RS注解;
- 支持可插拔的HTTP编码器和解码器;
- 支持Hystrix和它的Fallback;
- 支持Ribbon的负载均衡;
- 支持HTTP请求和响应的压缩。
Spring Cloud Feign致力于处理客户端与服务器之间的调用需求,简单来说,使用Spring Cloud Feign组件,他本身整合了Ribbon和Hystrix。可设计一套稳定可靠的弹性客户端调用方案,避免整个系统出现雪崩效应。
本文不会涉及Spring Cloud , 仅做Feign源码分析用。
前提 已有站点已有站点http://localhost:8080/echo/welcome/jim
实践 客户端代码EchoClientio.github.openfeign feign-core 11.8 io.github.openfeign feign-slf4j 11.8
public interface EchoClient {
@Headers({"Accept:*
void apply(RequestTemplate template);
}
Capability
public interface Capability {
static E enrich(E componentToEnrich, List capabilities) {
return capabilities.stream()
// invoke each individual capability and feed the result to the next one.
// This is equivalent to:
// Capability cap1 = ...;
// Capability cap2 = ...;
// Capability cap2 = ...;
// Contract contract = ...;
// Contract contract1 = cap1.enrich(contract);
// Contract contract2 = cap2.enrich(contract1);
// Contract contract3 = cap3.enrich(contract2);
// or in a more compact version
// Contract enrichedContract = cap3.enrich(cap2.enrich(cap1.enrich(contract)));
.reduce(
componentToEnrich,
(component, capability) -> invoke(component, capability),
(component, enrichedComponent) -> enrichedComponent);
}
static E invoke(E target, Capability capability) {
return Arrays.stream(capability.getClass().getMethods())
.filter(method -> method.getName().equals("enrich"))
.filter(method -> method.getReturnType().isInstance(target))
.findFirst()
.map(method -> {
return (E) method.invoke(capability, target);
})
.orElse(target);
}
default Client enrich(Client client) {
return client;
}
}
源码分析
Feign.builder()..newInstance(Target.EmptyTarget.create(EchoClient.class));
buildpublic abstract class Feign {
private InvocationHandlerFactory invocationHandlerFactory = new InvocationHandlerFactory.Default();
public Feign build() {
//一系列Capability.enrich()增强....
//1.
SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =
new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger,
logLevel, decode404, closeAfterDecode, propagationPolicy, forceDecoding);
//2.
ParseHandlersByName handlersByName =
new ParseHandlersByName(contract, options, encoder, decoder, queryMapEncoder,
errorDecoder, synchronousMethodHandlerFactory);
//3. 构建ReflectiveFeign返回
return new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder);
}
}
}
1.SynchronousMethodHandler
final class SynchronousMethodHandler implements MethodHandler {
static class Factory {
public MethodHandler create(Target> target,
MethodMetadata md,
RequestTemplate.Factory buildTemplateFromArgs,
Options options,
Decoder decoder,
ErrorDecoder errorDecoder) {
//a. factory创建 SynchronousMethodHandler
return new SynchronousMethodHandler(target, client, retryer, requestInterceptors, logger,
logLevel, md, buildTemplateFromArgs, options, decoder,
errorDecoder, decode404, closeAfterDecode, propagationPolicy, forceDecoding);
}
}
@Override
public Object invoke(Object[] argv) throws Throwable {
//1.1 使用传递来的方法参数argv来创建请求模板RequestTemplate。 --- 见BuildTemplateByResolvingArgs
RequestTemplate template = buildTemplateFromArgs.create(argv);
//1.2 查找参数中是否存在Options: 用来定义如连接超时等配置
Options options = findOptions(argv);
Retryer retryer = this.retryer.clone();
while (true) {
//重试---略
//1.3 执行
return executeAndDecode(template, options);
}
}
Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
//1.4
Request request = targetRequest(template);
//略....
//1.5 调用client.execute() --- 内部调用 HttpURLConnection执行http请求
Response response = client.execute(request, options);
return decoder.decode(response, metadata.returnType());
}
//1.4
Request targetRequest(RequestTemplate template) {
//for-each 执行RequestInterceptor.apply(RequestTemplate)
for (RequestInterceptor interceptor : requestInterceptors) {
interceptor.apply(template);
}
//将RequestTemplate转换为实际的Request对象
return target.apply(template);
}
}
BuildTemplateByResolvingArgs
private static class BuildTemplateByResolvingArgs implements RequestTemplate.Factory {
protected final MethodMetadata metadata;
protected final Target> target;
RequestTemplate mutable = RequestTemplate.from(metadata.template());
mutable.feignTarget(target);
//Method中是否存在参数累心为URI,如果有,将该参数url设置为Target的url
if (metadata.urlIndex() != null) {
int urlIndex = metadata.urlIndex();
mutable.target(String.valueOf(argv[urlIndex]));
}
RequestTemplate template = resolve(argv, mutable, varBuilder);
//略.....
return template;
}
}
Target
中间讲解一段关于Target
public interface Target{ Class type(); String name(); String url(); public Request apply(RequestTemplate input); public static class HardCodedTarget implements Target { } public static class EmptyTarget implements Target { } }
例
new Target.HardCodedTarget(EchoClient.class,"http://localhost:8080/echo");
String result = client.welcome(URI.create(""),"jim");
//等价于
EchoClient client = feign.newInstance(Target.EmptyTarget.create(EchoClient.class));
String result = client.welcome(URI.create("http://localhost:8080/echo"),"jim");
client.execute
@Override
public Response execute(Request request, Options options) throws IOException {
HttpURLConnection connection = convertAndSend(request, options);
return convertResponse(connection, request);
}
2.ParseHandlersByName
public class ReflectiveFeign extends Feign {
static final class ParseHandlersByName {
public Map apply(Target target) {
//检查契约是否合规
List metadata = contract.parseAndValidateMetadata(target.type());
Map result = new LinkedHashMap();
for (MethodMetadata md : metadata) {
BuildTemplateByResolvingArgs buildTemplate;
if (!md.formParams().isEmpty() && md.template().bodyTemplate() == null) {
buildTemplate =
new BuildFormEncodedTemplateFromArgs(md, encoder, queryMapEncoder, target);
} else if (md.bodyIndex() != null || md.alwaysEncodeBody()) {
buildTemplate = new BuildEncodedTemplateFromArgs(md, encoder, queryMapEncoder, target);
} else {
buildTemplate = new BuildTemplateByResolvingArgs(md, queryMapEncoder, target);
}
//md.configkey == target.type + method.name +args 组成 方法的指纹id
//为各个方法创建 MethodHandler
result.put(md.configKey(),factory.create(target, md, buildTemplate, options, decoder, errorDecoder));
}
return result;
}
}
}
Feign.newInstance(Target)
public class ReflectiveFeign extends Feign {
private final ParseHandlersByName targetToHandlersByName;
private final InvocationHandlerFactory factory; // invocationHandlerFactory.Default
private final QueryMapEncoder queryMapEncoder;
ReflectiveFeign(ParseHandlersByName targetToHandlersByName, InvocationHandlerFactory factory,
QueryMapEncoder queryMapEncoder) {
this.targetToHandlersByName = targetToHandlersByName;
this.factory = factory;
this.queryMapEncoder = queryMapEncoder;
}
@Override
public T newInstance(Target target) {
//1 为target.targetType所有的方法 创建对应的 MethodHandler
Map nameToHandler = targetToHandlersByName.apply(target);
Map methodToHandler = new LinkedHashMap();
List defaultMethodHandlers = new LinkedList();
for (Method method : target.type().getMethods()) {
if (method.getDeclaringClass() == Object.class) {
continue;
} else if (Util.isDefault(method)) { //isDefault略...
DefaultMethodHandler handler = new DefaultMethodHandler(method);
defaultMethodHandlers.add(handler);
methodToHandler.put(method, handler);
} else {
//2 记录target.targetType中method 和它对应的targetType
methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
}
//3 InvocationHandlerFactory.Default创建代理对象
InvocationHandler handler = factory.create(target, methodToHandler);
//3 创建实例
T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),
new Class>[] {target.type()}, handler);
//5 default略...
for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
defaultMethodHandler.bindTo(proxy);
}
return proxy;
}
}
InvocationHandlerFactory.Default.create()
public interface InvocationHandlerFactory {
InvocationHandler create(Target target, Map dispatch);
interface MethodHandler {
Object invoke(Object[] argv) throws Throwable;
}
static final class Default implements InvocationHandlerFactory {
@Override
public InvocationHandler create(Target target, Map dispatch) {
return new ReflectiveFeign.FeignInvocationHandler(target, dispatch);
}
}
}
代理对象: ReflectiveFeign.FeignInvocationHandler
static class FeignInvocationHandler implements InvocationHandler {
private final Target target;
private final Map dispatch;
FeignInvocationHandler(Target target, Map dispatch) {
this.target = checkNotNull(target, "target");
this.dispatch = checkNotNull(dispatch, "dispatch for %s", target);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//找到method对应的 MethodHandler,执行invoke方法;
return dispatch.get(method).invoke(args);
}
}
时序图
执行原理:
- 创建EchoClient的代理类Proxy,它的invocationHandler类型是ReflectiveFeign.FeignInvocationHandler
- 根据Map
dispatch 找到method对应的MethodHandler,最终逻辑交由它来执行,此时的methoHandler类型为SynchronousMethodHandler
3.SynchronousMethodHandler 的操作分为如下步骤- 根据Contract和Target.type()解析List
metadata,创建空的RequestTemplate - 解析调用方法的args[],填充RequestTemplate
- 将RequestTemplate转换为Request
- 使用Client.execute(request,option),它内部使用HttpURLConnection来执行http请求。
- 根据Contract和Target.type()解析List
生成的代理类
详细生成方法: https://blog.csdn.net/it_freshman/article/details/78873842



