Spring Cloud Feign的工作机制是怎样的?

2026-05-21 03:383阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2608个文字,预计阅读时间需要11分钟。

Spring Cloud Feign的工作机制是怎样的?

Feign 是一个 HTTP 请求调用的轻量级框架,通过 Java 接口注解的方式调用 HTTP 请求,无需直接封装 HTTP 请求报文,简化了 HTTP 请求的开发过程。

什么是Feign?

Feign 的英文表意为“假装,伪装,变形”, 是一个github.com/OpenFeign/feign

Feign解决了什么问题?

封装了Http调用流程,更适合面向接口化的编程习惯 在服务调用的场景中,我们经常调用基于Http协议的服务,而我们经常使用到的框架可能有HttpURLConnection、Apache HttpComponnets、OkHttp3 、Netty等等,这些框架在基于自身的专注点提供了自身特性。而从角色划分上来看,他们的职能是一致的提供Http调用服务。具体流程如下:

Feign是如何设计的?

工作原理

  • 主程序入口添加了@EnableFeignClients注解开启对FeignClient扫描加载处理。根据Feign Client的开发规范,定义接口并加@FeignClientd注解。

  • 当程序启动时,会进行包扫描,扫描所有@FeignClients的注解的类,并且将这些信息注入Spring IOC容器中,当定义的的Feign接口中的方法被调用时,通过JDK动态代理方式,来生成具体的RequestTemplate。当生成代理时,Feign会为每个接口方法创建一个RequestTemplate对象,该对象封装可HTTP请求需要的全部信息,如请求参数名,请求方法等信息都是在这个过程中确定的。

  • 然后RequestTemplate生成Request,然后把Request交给Client去处理,这里指的Client可以是JDK原生的URLConnection、Apache的HttpClient、也可以是OKapi.github.com"); // Fetch and print a list of the contributors to this library. List<Contributor> contributors = github.contributors("OpenFeign", "feign"); for (Contributor contributor : contributors) { System.out.println(contributor.login + " (" + contributor.contributions + ")"); } } }

    在Feign 底层,通过基于面向接口的动态代理方式生成实现类,将请求调用委托到动态代理实现类,基本原理如下所示:

    public class ReflectiveFeign extends Feign { @Override public <T> T newInstance(Target<T> target) { //根据接口类和Contract协议解析方式,解析接口类上的方法和注解,转换成内部的MethodHandler处理方式 Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target); Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>(); List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>(); for (Method method : target.type().getMethods()) { if (method.getDeclaringClass() == Object.class) { continue; } else if (Util.isDefault(method)) { DefaultMethodHandler handler = new DefaultMethodHandler(method); defaultMethodHandlers.add(handler); methodToHandler.put(method, handler); } else { methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method))); } } InvocationHandler handler = factory.create(target, methodToHandler); // 基于Proxy.newProxyInstance 为接口类创建动态实现,将所有的请求转换给InvocationHandler 处理。 T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),new Class<?>[] {target.type()}, handler); for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) { defaultMethodHandler.bindTo(proxy); } return proxy; } }

    2、根据Contract协议规则,解析接口类的注解信息,解析成内部表现

    Feign 定义了转换协议,定义如下:

    public interface Contract { //传入接口定义,解析成相应的方法内部元数据表示 List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType); }

    默认Contract 实现

    Feign 默认有一套自己的协议规范,规定了一些注解,可以映射成对应的Http请求,如官方的一个例子:

    public interface GitHub { @RequestLine("GET /repos/{owner}/{repo}/contributors") List<Contributor> getContributors(@Param("owner") String owner, @Param("repo") String repository); class Contributor { String login; int contributions; } }

    上述的例子中,尝试调用GitHub.getContributors(“foo”,“myrepo”)的的时候,会转换成如下的HTTP请求:

    GET /repos/foo/myrepo/contributors HOST XXXX.XXX.XXX

    Feign 默认的协议规范

    注解 接口Target 使用说明 @RequestLine 方法上 定义HttpMethod 和 UriTemplate. UriTemplate 中使用{} 包裹的表达式,可以通过在方法参数上使用@Param 自动注入 @Param 方法参数 定义模板变量,模板变量的值可以使用名称的方式使用模板注入解析 @Headers 类上或者方法上 定义头部模板变量,使用@Param 注解提供参数值的注入。如果该注解添加在接口类上,则所有的请求都会携带对应的Header信息;如果在方法上,则只会添加到对应的方法请求上 @QueryMap 方法上 定义一个键值对或者 pojo,参数值将会被转换成URL上的 query 字符串上 @HeaderMap 方法上 定义一个HeaderMap, 与 UrlTemplate 和HeaderTemplate 类型,可以使用@Param 注解提供参数值

    具体FeignContract 是如何解析的,详情请参考代码: github.com/OpenFeign/feign/blob/master/core/src/main/java/feign/Contract.java

    2.1、基于Spring MVC的协议规范SpringMvcContract

    OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解 当前Spring Cloud 微服务解决方案中spring-cloud-starter-openfeign,在Feign的基础上支持了Spring MVC的注解,OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,也就是说 ,写客户端请求接口和像写服务端代码一样:客户端和服务端可以通过SDK的方式进行约定,客户端只需要引入服务端发布的SDK API,就可以使用面向接口的编码方式对接服务:

    3、基于RequestBean动态生成Request

    根据传入的Bean对象和注解信息,从中提取出相应的值,来构造Http Request 对象:

    4、使用Encoder 将Bean转换成 Http报文正文(消息解析和转码逻辑)

    Feign 最终会将请求转换成Http 消息发送出去,传入的请求对象最终会解析成消息体,如下所示:

    在接口定义上Feign做的比较简单,抽象出了Encoder 和decoder 接口:

    public interface Encoder { Type MAP_STRING_WILDCARD = Util.MAP_STRING_WILDCARD; //将实体对象转换成Http请求的消息正文中 void encode(Object var1, Type var2, RequestTemplate var3) throws EncodeException; public static class Default implements Encoder { public Default() { } public void encode(Object object, Type bodyType, RequestTemplate template) { if (bodyType == String.class) { template.body(object.toString()); } else if (bodyType == byte[].class) { template.body((byte[])((byte[])object), (Charset)null); } else if (object != null) { throw new EncodeException(String.format("%s is not a type supported by this encoder.", object.getClass())); } } } } public interface Decoder { //从Response 中提取Http消息正文,通过接口类声明的返回类型,消息自动装配 Object decode(Response response, Type type) throws IOException, DecodeException, FeignException; public class Default extends StringDecoder { @Override public Object decode(Response response, Type type) throws IOException { if (response.status() == 404 || response.status() == 204) return Util.emptyValueOf(type); if (response.body() == null) return null; if (byte[].class.equals(type)) { return Util.toByteArray(response.body().asInputStream()); } return super.decode(response, type); } } }

    目前Feign 有以下实现:

    Encoder/ Decoder 实现 说明 JacksonEncoder,JacksonDecoder 基于 Jackson 格式的持久化转换协议 GsonEncoder,GsonDecoder 基于Google GSON 格式的持久化转换协议 SaxEncoder,SaxDecoder 基于XML 格式的Sax 库持久化转换协议 JAXBEncoder,JAXBDecoder 基于XML 格式的JAXB 库持久化转换协议 ResponseEntityEncoder,ResponseEntityDecoder Spring MVC 基于ResponseEntity< T > 返回格式的转换协议 SpringEncoder,SpringDecoder 基于Spring MVC HttpMessageConverters 一套机制实现的转换协议 ,应用于Spring Cloud 体系中

    5、拦截器负责对请求和返回进行装饰处理

    在请求转换的过程中,Feign 抽象出来了拦截器接口,用于用户自定义对请求的操作:

    public interface RequestInterceptor { /** * 可以在构造RequestTemplate 请求时,增加或者修改Header, Method, Body 等信息 */ void apply(RequestTemplate template); }

    比如,如果希望Http消息传递过程中被压缩,可以定义一个请求拦截器:

    public class FeignAcceptGzipEncodingInterceptor extends BaseRequestInterceptor { /** * Creates new instance of {@link FeignAcceptGzipEncodingInterceptor}. * @param properties the encoding properties */ protected FeignAcceptGzipEncodingInterceptor( FeignClientEncodingProperties properties) { super(properties); } /** * {@inheritDoc} */ @Override public void apply(RequestTemplate template) { // 在Header 头部添加相应的数据信息 addHeader(template, HttpEncoding.ACCEPT_ENCODING_HEADER, HttpEncoding.GZIP_ENCODING, HttpEncoding.DEFLATE_ENCODING); } }

    6、日志记录

    在发送和接收请求的时候,Feign定义了统一的日志门面来输出日志信息 , 并且将日志的输出定义了四个等级:

    级别 说明 NONE 不做任何记录 BASIC 只记录输出Http 方法名称、请求URL、返回状态码和执行时间 HEADERS 记录输出Http 方法名称、请求URL、返回状态码和执行时间 和 Header 信息 FULL 记录Request 和Response的Header,Body和一些请求元数据 public abstract class Logger { /** * Controls the level of logging. */ public enum Level { /** * No logging. */ NONE, /** * Log only the request method and URL and the response status code and execution time. */ BASIC, /** * Log the basic information along with request and response headers. */ HEADERS, /** * Log the headers, body, and metadata for both requests and responses. */ FULL } }

    7、基于重试器发送HTTP请求

    Feign 内置了一个重试器,当HTTP请求出现IO异常时,Feign会有一个最大尝试次数发送请求,以下是Feign核心 代码逻辑:

    final class SynchronousMethodHandler implements MethodHandler { @Override public Object invoke(Object[] argv) throws Throwable { //根据输入参数,构造Http 请求。 RequestTemplate template = buildTemplateFromArgs.create(argv); Options options = findOptions(argv); // 克隆出一份重试器 Retryer retryer = this.retryer.clone(); // 尝试最大次数,如果中间有结果,直接返回 while (true) { try { return executeAndDecode(template, options); } catch (RetryableException e) { try { retryer.continueOrPropagate(e); } catch (RetryableException th) { Throwable cause = th.getCause(); if (propagationPolicy == UNWRAP && cause != null) { throw cause; } else { throw th; } } if (logLevel != Logger.Level.NONE) { logger.logRetry(metadata.configKey(), logLevel); } continue; } } } }

    重试器有如下几个控制参数:

    重试参数 说明 默认值 period 初始重试时间间隔,当请求失败后,重试器将会暂停 初始时间间隔(线程 sleep 的方式)后再开始,避免强刷请求,浪费性能 100ms maxPeriod 当请求连续失败时,重试的时间间隔将按照:long interval = (long) (period * Math.pow(1.5, attempt - 1)); 计算,按照等比例方式延长,但是最大间隔时间为 maxPeriod, 设置此值能够避免 重试次数过多的情况下执行周期太长 1000ms maxAttempts 最大重试次数 5

    具体的代码实现可参考: github.com/OpenFeign/feign/blob/master/core/src/main/java/feign/Retryer.java

    8、发送Http请求

    Feign 真正发送HTTP请求是委托给 feign.Client 来做的:

    public interface Client { //执行Http请求,并返回Response Response execute(Request request, Options options) throws IOException; }

    Feign 默认底层通过JDK 的 java.net.HttpURLConnection 实现了feign.Client接口类,在每次发送请求的时候,都会创建新的HttpURLConnection 链接,这也就是为什么默认情况下Feign的性能很差的原因。可以通过拓展该接口,使用Apache HttpClient 或者OkHttp3等基于连接池的高性能Http客户端,我们项目内部使用的就是OkHttp3作为Http 客户端。

    三、Feign性能优化

    Feign 整体框架非常小巧,在处理请求转换和消息解析的过程中,基本上没什么时间消耗。真正影响性能的,是处理Http请求的环节。由于默认情况下,Feign采用的是JDK的HttpURLConnection,所以整体性能并不高。需要进行性能优化,通常采用ApacheHttpClient或者OKHttp,加入连接池技术。

    3.1、使用ApacheHttpClient

    相关类:

    org.springframework.cloud.openfeign.ribbon.HttpClientFeignLoadBalancedConfiguration org.springframework.cloud.openfeign.support.FeignHttpClientProperties

    引入依赖:

    <!-- Http Client 支持 --> <dependency> <groupId>org.apache.www.icode9.com/content-4-628558.html

    Spring Cloud Feign的工作机制是怎样的?

    blog.csdn.net/luanlouis/article/details/82821294

本文共计2608个文字,预计阅读时间需要11分钟。

Spring Cloud Feign的工作机制是怎样的?

Feign 是一个 HTTP 请求调用的轻量级框架,通过 Java 接口注解的方式调用 HTTP 请求,无需直接封装 HTTP 请求报文,简化了 HTTP 请求的开发过程。

什么是Feign?

Feign 的英文表意为“假装,伪装,变形”, 是一个github.com/OpenFeign/feign

Feign解决了什么问题?

封装了Http调用流程,更适合面向接口化的编程习惯 在服务调用的场景中,我们经常调用基于Http协议的服务,而我们经常使用到的框架可能有HttpURLConnection、Apache HttpComponnets、OkHttp3 、Netty等等,这些框架在基于自身的专注点提供了自身特性。而从角色划分上来看,他们的职能是一致的提供Http调用服务。具体流程如下:

Feign是如何设计的?

工作原理

  • 主程序入口添加了@EnableFeignClients注解开启对FeignClient扫描加载处理。根据Feign Client的开发规范,定义接口并加@FeignClientd注解。

  • 当程序启动时,会进行包扫描,扫描所有@FeignClients的注解的类,并且将这些信息注入Spring IOC容器中,当定义的的Feign接口中的方法被调用时,通过JDK动态代理方式,来生成具体的RequestTemplate。当生成代理时,Feign会为每个接口方法创建一个RequestTemplate对象,该对象封装可HTTP请求需要的全部信息,如请求参数名,请求方法等信息都是在这个过程中确定的。

  • 然后RequestTemplate生成Request,然后把Request交给Client去处理,这里指的Client可以是JDK原生的URLConnection、Apache的HttpClient、也可以是OKapi.github.com"); // Fetch and print a list of the contributors to this library. List<Contributor> contributors = github.contributors("OpenFeign", "feign"); for (Contributor contributor : contributors) { System.out.println(contributor.login + " (" + contributor.contributions + ")"); } } }

    在Feign 底层,通过基于面向接口的动态代理方式生成实现类,将请求调用委托到动态代理实现类,基本原理如下所示:

    public class ReflectiveFeign extends Feign { @Override public <T> T newInstance(Target<T> target) { //根据接口类和Contract协议解析方式,解析接口类上的方法和注解,转换成内部的MethodHandler处理方式 Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target); Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>(); List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>(); for (Method method : target.type().getMethods()) { if (method.getDeclaringClass() == Object.class) { continue; } else if (Util.isDefault(method)) { DefaultMethodHandler handler = new DefaultMethodHandler(method); defaultMethodHandlers.add(handler); methodToHandler.put(method, handler); } else { methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method))); } } InvocationHandler handler = factory.create(target, methodToHandler); // 基于Proxy.newProxyInstance 为接口类创建动态实现,将所有的请求转换给InvocationHandler 处理。 T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),new Class<?>[] {target.type()}, handler); for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) { defaultMethodHandler.bindTo(proxy); } return proxy; } }

    2、根据Contract协议规则,解析接口类的注解信息,解析成内部表现

    Feign 定义了转换协议,定义如下:

    public interface Contract { //传入接口定义,解析成相应的方法内部元数据表示 List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType); }

    默认Contract 实现

    Feign 默认有一套自己的协议规范,规定了一些注解,可以映射成对应的Http请求,如官方的一个例子:

    public interface GitHub { @RequestLine("GET /repos/{owner}/{repo}/contributors") List<Contributor> getContributors(@Param("owner") String owner, @Param("repo") String repository); class Contributor { String login; int contributions; } }

    上述的例子中,尝试调用GitHub.getContributors(“foo”,“myrepo”)的的时候,会转换成如下的HTTP请求:

    GET /repos/foo/myrepo/contributors HOST XXXX.XXX.XXX

    Feign 默认的协议规范

    注解 接口Target 使用说明 @RequestLine 方法上 定义HttpMethod 和 UriTemplate. UriTemplate 中使用{} 包裹的表达式,可以通过在方法参数上使用@Param 自动注入 @Param 方法参数 定义模板变量,模板变量的值可以使用名称的方式使用模板注入解析 @Headers 类上或者方法上 定义头部模板变量,使用@Param 注解提供参数值的注入。如果该注解添加在接口类上,则所有的请求都会携带对应的Header信息;如果在方法上,则只会添加到对应的方法请求上 @QueryMap 方法上 定义一个键值对或者 pojo,参数值将会被转换成URL上的 query 字符串上 @HeaderMap 方法上 定义一个HeaderMap, 与 UrlTemplate 和HeaderTemplate 类型,可以使用@Param 注解提供参数值

    具体FeignContract 是如何解析的,详情请参考代码: github.com/OpenFeign/feign/blob/master/core/src/main/java/feign/Contract.java

    2.1、基于Spring MVC的协议规范SpringMvcContract

    OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解 当前Spring Cloud 微服务解决方案中spring-cloud-starter-openfeign,在Feign的基础上支持了Spring MVC的注解,OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,也就是说 ,写客户端请求接口和像写服务端代码一样:客户端和服务端可以通过SDK的方式进行约定,客户端只需要引入服务端发布的SDK API,就可以使用面向接口的编码方式对接服务:

    3、基于RequestBean动态生成Request

    根据传入的Bean对象和注解信息,从中提取出相应的值,来构造Http Request 对象:

    4、使用Encoder 将Bean转换成 Http报文正文(消息解析和转码逻辑)

    Feign 最终会将请求转换成Http 消息发送出去,传入的请求对象最终会解析成消息体,如下所示:

    在接口定义上Feign做的比较简单,抽象出了Encoder 和decoder 接口:

    public interface Encoder { Type MAP_STRING_WILDCARD = Util.MAP_STRING_WILDCARD; //将实体对象转换成Http请求的消息正文中 void encode(Object var1, Type var2, RequestTemplate var3) throws EncodeException; public static class Default implements Encoder { public Default() { } public void encode(Object object, Type bodyType, RequestTemplate template) { if (bodyType == String.class) { template.body(object.toString()); } else if (bodyType == byte[].class) { template.body((byte[])((byte[])object), (Charset)null); } else if (object != null) { throw new EncodeException(String.format("%s is not a type supported by this encoder.", object.getClass())); } } } } public interface Decoder { //从Response 中提取Http消息正文,通过接口类声明的返回类型,消息自动装配 Object decode(Response response, Type type) throws IOException, DecodeException, FeignException; public class Default extends StringDecoder { @Override public Object decode(Response response, Type type) throws IOException { if (response.status() == 404 || response.status() == 204) return Util.emptyValueOf(type); if (response.body() == null) return null; if (byte[].class.equals(type)) { return Util.toByteArray(response.body().asInputStream()); } return super.decode(response, type); } } }

    目前Feign 有以下实现:

    Encoder/ Decoder 实现 说明 JacksonEncoder,JacksonDecoder 基于 Jackson 格式的持久化转换协议 GsonEncoder,GsonDecoder 基于Google GSON 格式的持久化转换协议 SaxEncoder,SaxDecoder 基于XML 格式的Sax 库持久化转换协议 JAXBEncoder,JAXBDecoder 基于XML 格式的JAXB 库持久化转换协议 ResponseEntityEncoder,ResponseEntityDecoder Spring MVC 基于ResponseEntity< T > 返回格式的转换协议 SpringEncoder,SpringDecoder 基于Spring MVC HttpMessageConverters 一套机制实现的转换协议 ,应用于Spring Cloud 体系中

    5、拦截器负责对请求和返回进行装饰处理

    在请求转换的过程中,Feign 抽象出来了拦截器接口,用于用户自定义对请求的操作:

    public interface RequestInterceptor { /** * 可以在构造RequestTemplate 请求时,增加或者修改Header, Method, Body 等信息 */ void apply(RequestTemplate template); }

    比如,如果希望Http消息传递过程中被压缩,可以定义一个请求拦截器:

    public class FeignAcceptGzipEncodingInterceptor extends BaseRequestInterceptor { /** * Creates new instance of {@link FeignAcceptGzipEncodingInterceptor}. * @param properties the encoding properties */ protected FeignAcceptGzipEncodingInterceptor( FeignClientEncodingProperties properties) { super(properties); } /** * {@inheritDoc} */ @Override public void apply(RequestTemplate template) { // 在Header 头部添加相应的数据信息 addHeader(template, HttpEncoding.ACCEPT_ENCODING_HEADER, HttpEncoding.GZIP_ENCODING, HttpEncoding.DEFLATE_ENCODING); } }

    6、日志记录

    在发送和接收请求的时候,Feign定义了统一的日志门面来输出日志信息 , 并且将日志的输出定义了四个等级:

    级别 说明 NONE 不做任何记录 BASIC 只记录输出Http 方法名称、请求URL、返回状态码和执行时间 HEADERS 记录输出Http 方法名称、请求URL、返回状态码和执行时间 和 Header 信息 FULL 记录Request 和Response的Header,Body和一些请求元数据 public abstract class Logger { /** * Controls the level of logging. */ public enum Level { /** * No logging. */ NONE, /** * Log only the request method and URL and the response status code and execution time. */ BASIC, /** * Log the basic information along with request and response headers. */ HEADERS, /** * Log the headers, body, and metadata for both requests and responses. */ FULL } }

    7、基于重试器发送HTTP请求

    Feign 内置了一个重试器,当HTTP请求出现IO异常时,Feign会有一个最大尝试次数发送请求,以下是Feign核心 代码逻辑:

    final class SynchronousMethodHandler implements MethodHandler { @Override public Object invoke(Object[] argv) throws Throwable { //根据输入参数,构造Http 请求。 RequestTemplate template = buildTemplateFromArgs.create(argv); Options options = findOptions(argv); // 克隆出一份重试器 Retryer retryer = this.retryer.clone(); // 尝试最大次数,如果中间有结果,直接返回 while (true) { try { return executeAndDecode(template, options); } catch (RetryableException e) { try { retryer.continueOrPropagate(e); } catch (RetryableException th) { Throwable cause = th.getCause(); if (propagationPolicy == UNWRAP && cause != null) { throw cause; } else { throw th; } } if (logLevel != Logger.Level.NONE) { logger.logRetry(metadata.configKey(), logLevel); } continue; } } } }

    重试器有如下几个控制参数:

    重试参数 说明 默认值 period 初始重试时间间隔,当请求失败后,重试器将会暂停 初始时间间隔(线程 sleep 的方式)后再开始,避免强刷请求,浪费性能 100ms maxPeriod 当请求连续失败时,重试的时间间隔将按照:long interval = (long) (period * Math.pow(1.5, attempt - 1)); 计算,按照等比例方式延长,但是最大间隔时间为 maxPeriod, 设置此值能够避免 重试次数过多的情况下执行周期太长 1000ms maxAttempts 最大重试次数 5

    具体的代码实现可参考: github.com/OpenFeign/feign/blob/master/core/src/main/java/feign/Retryer.java

    8、发送Http请求

    Feign 真正发送HTTP请求是委托给 feign.Client 来做的:

    public interface Client { //执行Http请求,并返回Response Response execute(Request request, Options options) throws IOException; }

    Feign 默认底层通过JDK 的 java.net.HttpURLConnection 实现了feign.Client接口类,在每次发送请求的时候,都会创建新的HttpURLConnection 链接,这也就是为什么默认情况下Feign的性能很差的原因。可以通过拓展该接口,使用Apache HttpClient 或者OkHttp3等基于连接池的高性能Http客户端,我们项目内部使用的就是OkHttp3作为Http 客户端。

    三、Feign性能优化

    Feign 整体框架非常小巧,在处理请求转换和消息解析的过程中,基本上没什么时间消耗。真正影响性能的,是处理Http请求的环节。由于默认情况下,Feign采用的是JDK的HttpURLConnection,所以整体性能并不高。需要进行性能优化,通常采用ApacheHttpClient或者OKHttp,加入连接池技术。

    3.1、使用ApacheHttpClient

    相关类:

    org.springframework.cloud.openfeign.ribbon.HttpClientFeignLoadBalancedConfiguration org.springframework.cloud.openfeign.support.FeignHttpClientProperties

    引入依赖:

    <!-- Http Client 支持 --> <dependency> <groupId>org.apache.www.icode9.com/content-4-628558.html

    Spring Cloud Feign的工作机制是怎样的?

    blog.csdn.net/luanlouis/article/details/82821294