type
status
date
slug
summary
tags
category
icon
password

1、Feign核心架构和原理

Feign 调用的核心原理:通过一系列的封装和注解,讲 @FeignClient 注解修饰的接口方法,转换成调用远程服务的 HTTP 请求,经过均衡负载器的处理将请求发送给远程服务,并解析请求结果返回给调用者,调用者在调用远程服务的方法的时候感觉就跟调用本地方法一样透明
借助网上的一张图解释这个流程:
 
notion image

2、Feign调用的流程

2.1 Feign调用的初始化过程

2.1.1 注解驱动机制

Feign的启动始于@EnableFeignClients注解,该注解一般放在启动类上,通过FeignClientsRegistrar类实现接口扫描和动态代理创建:
FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar接口,在registerBeanDefinitions方法中完成:
  1. 扫描所有被@FeignClient标记的接口
  1. 为每个接口创建FeignClientFactoryBean工厂Bean
  1. 注册 BeanDefinition 到 Spring 容器

2.1.2 代理对象创建流程

当 Spring 容器初始化 Feign客户端时,会调用FeignClientFactoryBean.getObject()方法,核心代码如下:
最终会调用ReflectiveFeign.newInstance()方法创建 JDK 动态代理对象

2.2 动态代理与调用拦截机制

2.2.1 代理类生成

ReflectiveFeign.newInstance()方法核心逻辑:
这里创建的 InvocationHandler 实例,是 Feign 自己基于 java.lang.reflect 包中的 InvocationHandler 接口实现的代理类 FeignInvocationHandler ,这个代理类是 ReflectiveFeign 的内部类。
这个内部类的两个核心关注点:
  • dispatch 属性:是一个Map<Method, MethodHandler>,存储了每个方法对应的处理器。
  • invoke 方法:选择方法对应的处理器执行方法。

2.2.2 方法调用拦截

当调用 Feign 接口方法时,会进入FeignInvocationHandler.invoke()方法,这里会选择方法对应的 MethodHandlerinvoke 方法,完成实际的 HTTP 请求和结果的处理。
MethodHandler 是 Feign 定义的独立的接口,定义在 InvocationHandlerFactory 接口中,仅仅拥有一个 invoke 方法。
MethodHandler 的invoke 方法,主要职责是完成实际远程URL请求,然后返回解码后的远程 URL 的响应结果。Feign 提供了默认的 SynchronousMethodHandler 实现类,提供了基本的远程 URL 的同步请求处理。
notion image

2.3 请求构建与执行流程

2.3.1 请求模板构建

SynchronousMethodHandler.invoke()是实际处理HTTP请求的核心:
SynchronousMethodHandlerinvoke方法,调用了自己的 executeAndDecode 请求执行和结果解码方法。该方法的工作步骤:
  1. 首先通 RequestTemplate 请求模板实例,生成远程 URL 请求实例 request;
  1. 然后用自己的 feign 客户端 client 属性,excecute 执行请求,并且获取 response 响应;
  1. 对 response 响应进行结果解码。
这里的 client 属性,基于 Feign 自定义的 Client 接口,这是 Feign 中一个非常重要的组件,负责端到端的执行 URL 请求。

2.3.2 HTTP客户端执行

Client 接口是客户端的顶层接口
支持多种 HTTP 客户端实现:
  • Client.Default :默认的 feign.Client 客户端实现类,内部使用 HttpURLConnnection 完成 URL 请求处理。
  • ApacheHttpClient :基于 Apache HttpClient 开源组件的的 feign.Client 客户端实现类,需要另外引入 feign-httpclient 依赖。
  • OkHttpClient :基于 OkHttp3 开源组件的 feign.Client 客户端实现类,需要另外引入 feign-okhttp 依赖。
  • FeignBlockingLoadBalancerClient :基于 LoadBalancer 负载均衡的 feign.Client 客户端实现类,通过 LoadBalancerClient 选择服务实例,重构请求 URL 后委托给底层 HTTP 客户端(如 Apache HttpClient 或 OkHttp)执行请求。
在 Spring Cloud 环境中,默认使用FeignBlockingLoadBalancerClient实现负载均衡。

2.3.2 请求拦截器处理

请求会经过一系列拦截器处理,拦截器的顶层接口是 RequestInterceptor
内置拦截器包括:
  • BasicAuthRequestInterceptor:处理基础认证
  • FeignAcceptGzipEncodingInterceptor:处理编码类型
  • FeignContextGzipEncodingInterceptor:处理内容压缩

2.4 均衡负载处理

均衡负载器的顶级接口是 LoadBalancerClient ,这里面最重要的是 choose 方法和 execute 方法。
LoadBalancerClient 接口的默认实现类是 BlockingLoadBalancerClient,这一个同步/阻塞式的客户端均衡负载实现。他的作用有:
  • 服务实例选择:根据服务ID从注册中心获取可用实例列表
  • 负载均衡策略:应用配置的负载均衡算法(如轮询、随机等),默认为轮询(实现类为 RoundRobinLoadBalancer
  • 服务调用:自动将 @FeignClient 的服务名解析为实际地址。

2.5 调用流程时序图

写一个最简单的远程调用例子,消费者控制器 ConsumerController
@FeignClient 注解修饰的接口
生产者控制器 ProviderController
当调用 ConsumerController.helloFeign() 方法时,整个流程时序图如下所示:
notion image

3、性能优化建议

1、使用连接池
使用 Apache HttpClient 或 OkHttp 替换默认的 HttpURLConnection。以 Apache HttpClient 为例:
第一步,引入依赖
第二步,启用配置,在 application.yml 中配置:
第三步,自定义配置
2、合理配置超时
3、启用压缩
4、缓存设计:对不变的结果进行适当缓存
5、日志优化:合理设置日志级别避免性能损耗
ShardingSphere使用总结Spring Cloud LoadBalancer 负载均衡策略机制
Loading...