@Author:zxw
@Email:502513206@qq.com


1.前言

在springcloud的微服务体系中,有这么一个框架Feign能够提供我们调用远程服务就像调用本地服务一样,我们先抛开spring对Feign的封装,而是直接从Feign入手来看看Feign的内部组成与调用逻辑是怎么样的,那么就从如下我写的一个访问Gitee调用的代码入手看Feign。

  1. static Gitee connect() {
  2. final Decoder decoder = new GsonDecoder();
  3. final Encoder encoder = new GsonEncoder();
  4. return Feign.builder()
  5. .encoder(encoder)
  6. .decoder(decoder)
  7. .logger(new Logger.ErrorLogger())
  8. .logLevel(Logger.Level.BASIC)
  9. .requestInterceptor(template -> {
  10. // template.header(
  11. // "Authorization",
  12. // "token 383f1c1b474d8f05a21e7964976ab0d403fee071");
  13. })
  14. .options(new Request.Options(10, TimeUnit.SECONDS, 60, TimeUnit.SECONDS, true))
  15. .target(Gitee.class, "https://gitee.com");
  16. }

2.FeignBuilder

我们可以通过Feign中的Builder构建一个访问的client对象,那么就从这个Builder对象入手。
用过feign的都知道,feign通过在接口上标注注解为我们生成代理类以达到调用的目的,那么对于注解有着自己的一套解析方式

  1. private Contract contract = new Contract.Default();

用过RestTemplate应该都知道在发起请求时,可以在RestTemplate中加入拦截器,实现我们自己的逻辑,例如增加请求头等,在Feign也可以添加拦截器,如下

private final List<RequestInterceptor> requestInterceptors = new ArrayList<RequestInterceptor>();

如果对netty有过了解的应该都知道编写服务端和客户端时,我们可以对网络传输自定义编码和解码器按照我们想要的方式来传输,feign中也提供了对应的编码和解码,如下

private Encoder encoder = new Encoder.Default();
private Decoder decoder = new Decoder.Default();
private QueryMapEncoder queryMapEncoder = new FieldQueryMapEncoder();
private ErrorDecoder errorDecoder = new ErrorDecoder.Default();

在发起http请求时,一些接口的响应时间以及http连接建立时间过长导致资源被占用,这时我们需要一些参数来控制请求超时,这里Feign提供了Options类提供配置

private Options options = new Options();

有了请求的基本信息后,我们需要一个客户端来发送请求,在feign中为Client接口的实例,这意味着我们可以自己扩展Client实现自己的发送端。

private Client client = new Client.Default(null, null);

对于网络中的请求总是存在不稳定性,也许一次成功一次失败,这时我们就需要一个重发器来帮助我们重新发起请求,Feign会为我们提供了重试器

private Retryer retryer = new Retryer.Default();

3.总结

对于Feign中的主要元数据有如下几个

  1. 客户端:发起远程调用的执行者
  2. Options:封装我们请求信息基本参数,如uri,Http Method等
  3. 拦截器:添加请求自定义的逻辑,比如增加请求头
  4. 编码器:对请求进行编码
  5. 解码:对于请求解码
  6. Contract:解析Feign提供的注解标注的值

image.png