OpenFeign 基本介绍和原理了解

这篇具有很好参考价值的文章主要介绍了OpenFeign 基本介绍和原理了解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

了解 OpenFeign

OpenFeign 组件的前身是 Netflix Feign 项目。后来 Feign 项目被贡献给了开源组织,才有了今天使用的 Spring Cloud OpenFeign 组件。
OpenFeign 提供了一种声明式的远程调用接口,它可以大幅简化远程调用的编程体验。用一个代码片段看一下,由 OpenFeign 发起的远程服务调用的代码风格是什么样的。

String response = helloWorldService.hello("Spring Cloud");

可以发现,使用 OpenFeign 组件来实现远程调用非常简单,就像使用本地方法一样,只要一行代码就能实现 WebClient 组件好几行代码干的事情。而且这段代码不包含任何业务无关的信息,完美实现了调用逻辑和业务逻辑之间的职责分离。

OpenFeign 组件背后的工作流程

OpenFeign 使用了一种动态代理技术来封装远程服务调用的过程,在上面的例子中看到的 helloWorldService 其实是一个特殊的接口,它是由 OpenFeign 组件中的 FeignClient 注解所声明的接口。

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

@FeignClient(value = "hello-world-service")
public interface HelloWorldService {   
  @PostMapping("/sayHello")   
  String hello(String guestName);
}

远程服务调用的信息被写在了 FeignClient 接口中。在上面的代码里,可以看到,服务的名称、接口类型、访问路径已经通过注解做了声明。OpenFeign 通过解析这些注解标签生成一个动态代理类,这个代理类会将接口调用转化为一个远程服务调用的 Request,并发送给目标服务。

OpenFeign 的动态代理

在项目初始化阶段,OpenFeign 会生成一个代理类,对所有通过FeignClient 接口发起的远程调用进行动态代理。如图:
OpenFeign 基本介绍和原理了解
上图中的步骤中,在项目启动阶段加载完成的是 1 ~ 3步 ,只有第 4 步(调用远程服务)是发生在项目的运行阶段
关键步骤描述:

  1. 在项目启动阶段,OpenFeign 框架会发起一个主动的扫包流程,从指定的目录下扫描并加载所有被 @FeignClient 注解修饰的接口。
  2. OpenFeign 会针对每一个 FeignClient 接口生成一个动态代理对象,即图中的 FeignProxyService,这个代理对象在继承关系上属于 FeignClient 注解所修饰的接口的实例。
  3. 这个动态代理对象会被添加到 Spring 上下文中,并注入到对应的服务里,也就是图中的 LocalService 服务。
  4. LocalService 会发起底层方法调用。实际上这个方法调用会被 OpenFeign 生成的代理对象接管,由代理对象发起一个远程服务调用,并将调用的结果返回给 LocalService。

OpenFeign 是如何通过动态代理技术创建代理对象的?

OpenFeign 组件加载过程的重要阶段,如图:
OpenFeign 基本介绍和原理了解
OpenFeign 动态代理类的创建过程:

  1. 项目加载:在项目的启动阶段,EnableFeignClients 注解扮演了启动开关的角色,它使用 Spring 框架的 Import 注解导入了 FeignClientsRegistrar 类,开始了 OpenFeign 组件的加载过程。
@SpringBootApplication
@EnableFeignClients
public class HelloWorldApplication {

    public static void main(String[] args) {
        SpringApplication.run(HelloWorldApplication .class, args);
    }

}
  1. 扫包:FeignClientsRegistrar 负责 FeignClient 接口的加载,它会在指定的包路径下扫描所有的 FeignClients 类,并构造 FeignClientFactoryBean 对象来解析 FeignClient 接口。
  2. 解析 FeignClient 注解:FeignClientFactoryBean 有两个重要的功能,一个是解析 FeignClient 接口中的请求路径和降级函数的配置信息;另一个是触发动态代理的构造过程。
  3. 构建动态代理对象:ReflectiveFeign 包含了 OpenFeign 动态代理的核心逻辑,它主要负责创建出 FeignClient 接口的动态代理对象。ReflectiveFeign 在这个过程中有两个重要任务:一个是解析 FeignClient 接口上各个方法级别的注解。将其中的远程接口 URL、接口类型(GET、POST 等)、各个请求参数等封装成元数据,并为每一个方法生成一个对应的 MethodHandler 类作为方法级别的代理;另一个重要任务是将这些 MethodHandler 方法代理做进一步封装,通过 Java 标准的动态代理协议,构建一个实现了 InvocationHandler 接口的动态代理对象,并将这个动态代理对象绑定到 FeignClient 接口上。这样一来,所有发生在 FeignClient 接口上的调用,最终都会由它背后的动态代理对象来承接。
    MethodHandler 的构建过程涉及到了复杂的元数据解析,OpenFeign 组件将 FeignClient 接口上的各种注解封装成元数据,并利用这些元数据把一个方法调用“翻译”成一个远程调用的 Request 请求。
    元数据的解析是依赖于 OpenFeign 组件中的 Contract 协议解析功能。Contract 是 OpenFeign 组件中定义的顶层抽象接口,它有一系列的具体实现,其中 SpringMvcContract 这个类名字中就能看出来,它是专门用来解析 Spring MVC 标签的。
    SpringMvcContract 的继承结构是 :SpringMvcContract->BaseContract->Contract。
    这里拿一段 SpringMvcContract 的代码块,理解它是如何将注解解析为元数据的。这段代码的主要功能是解析 FeignClient 方法级别上定义的 Spring MVC 注解。
// 解析FeignClient接口方法级别上的RequestMapping注解
protected void processAnnotationOnMethod(MethodMetadata data, Annotation methodAnnotation, Method method) {
   
   // 如果方法上没有使用RequestMapping注解,则不进行解析
   // 其实GetMapping、PostMapping等注解都属于RequestMapping注解
   if (!RequestMapping.class.isInstance(methodAnnotation)
         && !methodAnnotation.annotationType().isAnnotationPresent(RequestMapping.class)) {
      return;
   }

   // 获取RequestMapping注解实例
   RequestMapping methodMapping = findMergedAnnotation(method, RequestMapping.class);
   // 解析Http Method定义,即注解中的GET、POST、PUT、DELETE方法类型
   RequestMethod[] methods = methodMapping.method();
   // 如果没有定义methods属性则默认当前方法是个GET方法
   if (methods.length == 0) {
      methods = new RequestMethod[] { RequestMethod.GET };
   }
   checkOne(method, methods, "method");
   data.template().method(Request.HttpMethod.valueOf(methods[0].name()));

   // 解析Path属性,即方法上写明的请求路径
   checkAtMostOne(method, methodMapping.value(), "value");
   if (methodMapping.value().length > 0) {
      String pathValue = emptyToNull(methodMapping.value()[0]);
      if (pathValue != null) {
         pathValue = resolve(pathValue);
         // 如果path没有以斜杠开头,则补上/
         if (!pathValue.startsWith("/") && !data.template().path().endsWith("/")) {
            pathValue = "/" + pathValue;
         }
         data.template().uri(pathValue, true);
         if (data.template().decodeSlash() != decodeSlash) {
            data.template().decodeSlash(decodeSlash);
         }
      }
   }

   // 解析RequestMapping中定义的produces属性
   parseProduces(data, method, methodMapping);

   // 解析RequestMapping中定义的consumer属性
   parseConsumes(data, method, methodMapping);

   // 解析RequestMapping中定义的headers属性
   parseHeaders(data, method, methodMapping);
   data.indexToExpander(new LinkedHashMap<>());
}

通过上面的方法可以看到,OpenFeign 对 RequestMappings 注解的各个属性都做了解析。
如果项目中使用的是 GetMapping、PostMapping 之类的注解,没有使用 RequestMapping,那么 OpenFeign 也可以解析。以 GetMapping 为例,它对 RequestMapping 注解做了一层封装。如下代码片段,这个注解头上也挂了一个 RequestMapping 注解。因此 OpenFeign 可以正确识别 GetMapping 并完成加载。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {
// ...省略部分代码
}

OpenFeign调用过程

OpenFeign 其实底层调用的是 Feign 的方法,生成了代理类,使用的是 JDK 的动态代理,然后 bean 注入。
调用过程,就是代理类作为客户端向被调用方发送请求,接收相应的过程。其中,feign 自行封装了 JDK java.net 相关的网络请求方法,请求过程中还有 Loadbalancer 进行负载均衡;收到响应后,还会对响应类进行解析,取出正确的响应信息。文章来源地址https://www.toymoban.com/news/detail-421308.html

到了这里,关于OpenFeign 基本介绍和原理了解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 网络爬虫基本原理的介绍

    网络爬虫是一种计算机程序,它通过网络请求从不同的服务器收集和抓取信息,并存储在本地文件或数据库中。 网络爬虫的基本原理主要包含以下几个部分: 首先,选择爬行目标并获得初始URL,然后下载并解析这个URL,接着,根据提取出的新URL,继续进行重复下载和解析。

    2024年01月25日
    浏览(41)
  • 爬虫基本原理介绍、实现以及问题解决

    1. 前言 爬虫作为网络数据采集的重要工具,在当今互联网时代具有不可替代的作用。通过爬虫,我们可以获取到丰富的网络数据,用于各种用途,包括数据分析、业务决策、舆情监测等。 2. 爬虫能做什么 爬虫可以用于获取互联网上的各种数据,无论是文字、图片、视频还是

    2024年04月14日
    浏览(36)
  • 强大的JTAG边界扫描(1):基本原理介绍

    我是怎么了解到边界扫描的呢? 这就要从我淘到一块FPGA板卡的事情说起了。 前段时间我在某二手平台上淘了一块FPGA板子,它长这样: 板子的整体尺寸很小巧,和手掌差不多大,外设也很简单: 12v供电,带一个散热器 FPGA芯片是Xilinx XC7K325T,FFG676封装,芯片等级2I,生产日期

    2024年02月09日
    浏览(43)
  • Quartz核心原理之架构及基本元素介绍

    Quartz是一个作业调度框架,它可以与J2EE和J2SE应用相结合,也可以单独使用。它能够创建多个甚至数万个jobs这样复杂的程序,jobs可以做成标准的java组件或EJBS。Quartz很容易上手,创建一个任务仅需实现Job接口,该接口只有一个方法void execute(JobExecutionContext context) throws JobExecu

    2024年02月05日
    浏览(38)
  • 手写Openfeign实现原理——极简版

    最近开发cloud项目,里面涉及到服务间调用,最后使用的openfeign解决的,于是对于openfeign的底层原理有些兴趣了,提前透露一下底层无非就是使用一些http调用的工具帮助我们实现了请求调用 首先创建一个springboot项目 有一个发送请求的工具这里使用的ribbon 创建两个自定义注解

    2024年02月10日
    浏览(43)
  • 移动端1px-从基本原理到开源解决方案介绍

     1px 不够准确,应该说成 1  物理像素 为什么有 1px 这个问题? 实现 1px 有哪些方法?这些方法分别有哪些优缺点? 开源项目中使用的哪些解决方案? 如何在项目中处理 1px 的相关问题? 首先,我们要了解两个概念,一个是像素(pixel)可以简写为px,另外一个是设备像素比

    2024年02月07日
    浏览(35)
  • OpenFeign的简单介绍和功能实操

    本文主要做一下OpenFeign的简单介绍和功能实操,实操主要是OpenFeign的超时和重试,在阅读本文章前,请完成《Nacos 注册中心介绍与实操》内的Nacos多模块生产消费者项目 OpenFeign全名Spring Cloud OpenFeign,是SpringCloud开发团队基于Feign开发的框架,声明式Web服务客户端 Feign是一种声

    2024年02月06日
    浏览(34)
  • 大语言模型的预训练[1]:基本概念原理、神经网络的语言模型、Transformer模型原理详解、Bert模型原理介绍

    预训练属于迁移学习的范畴。现有的神经网络在进行训练时,一般基于反向传播(Back Propagation,BP)算法,先对网络中的参数进行随机初始化,再利用随机梯度下降(Stochastic Gradient Descent,SGD)等优化算法不断优化模型参数。而预训练的思想是,模型参数不再是随机初始化的

    2024年02月17日
    浏览(52)
  • Unity 热更新技术 | (一) 热更新的基本概念原理及主流热更新方案介绍

    🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN 🙉 🎄 学习专栏推荐:Unity系统学习专栏 🌲 游戏制作专栏推荐:游戏制作 🌲Unity实战100例专栏推荐:Unity 实战100例 教程 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! 📆 未来很长

    2024年02月01日
    浏览(56)
  • 原生OpenFeign相较于传统HTTP工具的优化和原理

    本篇介绍的是springcloud-openfeign的底层框架io.github.openfeign,重点不是框架如何使用,而是介绍Feign如何基于传统HTTP工具使用方式进行抽象改进,提升其灵活性,并简单介绍一下其抽象组件及主要组件的使用时机 以常用的OkHttp3工具框架为例,其一个大致的流程如下: 其流程从下

    2024年02月07日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包