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

Feign源码分析(without spring)

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

Feign源码分析(without spring)

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

maven依赖
   
      io.github.openfeign
      feign-core
      11.8
    
    
      io.github.openfeign
      feign-slf4j
      11.8
    
实践 客户端代码EchoClient
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));

build
public 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);
    }
}

时序图


执行原理:

  1. 创建EchoClient的代理类Proxy,它的invocationHandler类型是ReflectiveFeign.FeignInvocationHandler
  2. 根据Map dispatch 找到method对应的MethodHandler,最终逻辑交由它来执行,此时的methoHandler类型为SynchronousMethodHandler
    3.SynchronousMethodHandler 的操作分为如下步骤
    • 根据Contract和Target.type()解析List metadata,创建空的RequestTemplate
    • 解析调用方法的args[],填充RequestTemplate
    • 将RequestTemplate转换为Request
    • 使用Client.execute(request,option),它内部使用HttpURLConnection来执行http请求。

生成的代理类

详细生成方法: https://blog.csdn.net/it_freshman/article/details/78873842

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

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

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