前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试系列之-Spring Cloud Feign

面试系列之-Spring Cloud Feign

作者头像
用户4283147
发布2023-11-20 15:00:50
2150
发布2023-11-20 15:00:50
举报
文章被收录于专栏:对线JAVA面试对线JAVA面试
Feign的工作原理

  1. 主程序入口添加了@EnableFeignClients注解开启对FeignClient扫描加载处理。根据Feign Client的开发规范,定义接口并加@FeignClientd注解;
  2. 当程序启动时,会进行包扫描,扫描所有@FeignClients的注解的类,并且将这些信息注入Spring IOC容器中,当定义的的Feign接口中的方法被调用时,通过JDK动态代理方式,来生成具体的RequestTemplate。当生成代理时,Feign会为每个接口方法创建一个RequestTemplate对象,该对象封装可HTTP请求需要的全部信息,如请求参数名,请求方法等信息都是在这个过程中确定的;
  3. 然后RequestTemplate生成Request,然后把Request交给Client去处理,这里指的Client可以是JDK原生的URLConnection、Apache的HttpClient、也可以是OKhttp,最后Client被封装到LoadBalanceClient类,这个类结合Ribbon负载均衡发起服务之间的调用;
要点
基于面向接口的JDK动态代理方式生成实现类
基于RequestBean动态生成Request

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

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

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

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

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

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

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

代码语言:javascript
复制
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);
    }
基于重试器发送HTTP请求

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

代码语言:javascript
复制
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;
            }
        }
    }
}
http客户端扩展

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

日志记录

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

级别

说明

NONE

不做任何记录

BASIC

只记录输出Http 方法名称、请求URL、返回状态码和执行时间

HEADERS

记录输出Http 方法名称、请求URL、返回状态码和执行时间 和 Header 信息

FULL

记录Request 和Response的Header,Body和一些请求元数据

代码语言:javascript
复制
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
    }
}
Feign性能优化

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

代码语言:javascript
复制
<!-- Http Client 支持 -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>

<!-- Apache Http Client 对 Feign 支持 -->
<dependency>
    <groupId>com.netflix.feign</groupId>
    <artifactId>feign-httpclient</artifactId>
    <version>${feign-httpclient.version}</version>
</dependency>

### Feign 配置
feign:
  httpclient:
    # 是否开启 Http Client
    enabled: false
#    # 最大连接数,默认:200
#    max-connections: 200
#    # 最大路由,默认:50
#    max-connections-per-route: 50
#    # 连接超时,默认:2000/毫秒
#    connection-timeout: 2000
#    # 生存时间,默认:900L
#    time-to-live: 900
#    # 响应超时的时间单位,默认:TimeUnit.SECONDS
##    timeToLiveUnit: SECONDS
  okhttp:
    enabled: true
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-11-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 对线JAVA面试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Feign的工作原理
    • 要点
      • 基于面向接口的JDK动态代理方式生成实现类
      • 基于RequestBean动态生成Request
      • 使用Encoder 将Bean转换成 Http报文正文(消息解析和转码逻辑)
      • 拦截器负责对请求和返回进行装饰处理
      • 基于重试器发送HTTP请求
      • http客户端扩展
  • 日志记录
  • Feign性能优化
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档