SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解
作者:mmseoamin日期:2024-04-27

SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第1张

前言

在之前的博客中,我们介绍了RestTemplate的使用,博客文章如下连接。但是在使用RestTemplate的时候,需要把生产者的路径拼出来,非常繁琐,另外参数的传递的也比较繁琐,解决方案就是使用openFeign。

SpringCloud入门(RestTemplate + Ribbon)——微服务调用的方式 & RestTemplate的使用 & 使用nacos的服务名初步(Ribbon负载均衡)

本篇博客介绍OpenFeign,声明式的HTTP客户端,用于简化服务间的调用这一SpringCloud组件,并尝试对源码进行了初步分析。

SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第2张

目录

  • 前言
  • 引出
  • 初识OpenFeign
    • 为什么用feign?
    • Feign是什么
    • Feign的使用流程初步
      • 1.引入依赖
      • 2.主启动类加注解
      • 3.在消费端写feign接口
      • 4.controller中直接调用feign
      • 深入认识feign
        • 1.代理对象
        • 2.feign与ribbon的关系
        • 3.fegin的其他配置
          • (1)超时时间
          • (2)请求压缩
          • 4.日志级别的配置
            • (1)配置文件yml
            • (2)配置类配置
            • feign的源码分析
              • 1)@EnableFeignClients与@FeignClient
              • 2)请求的发送拆解
              • 总结

                引出


                1.spring提供的restTemplate,发送HTTP请求的客户端工具类;

                2.OpenFeign,声明式的HTTP客户端,用于简化服务间的调用;

                3.和ribbon的关系,其他的配置,超时时间,日志级别;

                4.源码分析,@EnableFeignClient和@FeignClient的作用;

                5.尝试分析OpenFeign请求发送的流程;

                SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第3张

                初识OpenFeign

                声明式的HTTP客户端,用于简化服务间的调用

                OpenFeign的主要特点和功能包括:

                1. 声明式的API定义:通过使用注解,开发者可以定义和描述服务间的API接口,包括请求方法、路径、参数、请求头等信息。这样可以使得服务间的调用代码更加简洁和易于维护。
                2. 自动化的服务发现和负载均衡:OpenFeign集成了服务注册中心,可以自动发现和调用其他微服务。它还支持负载均衡,可以根据配置的负载均衡策略选择合适的服务实例进行调用。
                3. 内置的请求和响应拦截器:OpenFeign提供了一些内置的拦截器,可以在请求和响应的不同阶段进行拦截和处理。开发者可以自定义拦截器来实现日志记录、错误处理等功能。
                4. 支持多种编码器和解码器:OpenFeign支持多种编码器和解码器,可以处理不同的数据格式,如JSON、XML等。开发者可以根据需要选择合适的编码器和解码器。
                5. 整合了Hystrix和Ribbon:OpenFeign与Hystrix和Ribbon等其他Spring Cloud组件集成,可以实现服务的容错和熔断机制,提高系统的可靠性和稳定性。

                总之,OpenFeign简化了微服务架构中的服务间调用,提供了一种简洁、声明式的方式来定义和调用服务API。它与Spring Cloud的其他组件集成良好,是构建和管理微服务架构的重要工具之一。

                为什么用feign?

                SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第4张

                上面的代码存在以下问题:

                • 远程调用需要拼接地址,不符合我们的使用习惯(注入一个对象,通过方法调用)
                • 参数拼接,如果参数比较复杂的话,拼接较为麻烦(参数为DTO的话)
                • 返回的result对象里面的data数据是一个Map数据结构

                  因此采用OpenFeign技术来解决上述问题

                  Feign是什么

                  Feign是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求。

                  Spring Cloud Feign是基于Netflix feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix 实现负载均衡和断路器,除了提供这两者的强大功能外,还提供了一种声明式的Web服务客户端定义的方式。

                  Spring Cloud Feign帮助我们定义和实现依赖服务接口的定义。在Spring Cloud feign的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring CloudRibbon时自行封装服务调用客户端的开发量。

                  通俗的讲:feign使远程调用的代码写法更加符合我们的编程习惯,也内置了负载均衡策略。

                  Feign的使用流程初步

                  1.引入依赖

                          
                              org.springframework.cloud
                              spring-cloud-starter-openfeign
                              2.2.6.RELEASE
                          
                  

                  2.主启动类加注解

                  import org.springframework.cloud.openfeign.EnableFeignClients;
                  

                  SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第5张

                  3.在消费端写feign接口

                  SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第6张

                  package com.tianju.consumer.api;
                  import org.springframework.cloud.openfeign.FeignClient;
                  import org.springframework.web.bind.annotation.GetMapping;
                  import org.springframework.web.bind.annotation.PathVariable;
                  // contextId唯一,可以随便写;
                  //@FeignClient(value = "springCloud-provider",contextId = "providerFeignTest") // openfeign用来远程连接
                  @FeignClient(value = "springCloud-provider",fallback = ProvideFallback.class) // openfeign用来远程连接
                  public interface IProvideFeign {
                      @GetMapping("/api/provider/hello")
                      String helloFeign();
                      /**
                       * 这个去调用生产者provider
                       * @param msg 路径变量信息
                       * @return 返回结果
                       */
                      @GetMapping("/api/provider/hiPath/{msg}")
                      String pet(@PathVariable("msg") String msg);
                  }
                  
                      @Autowired
                      private IProvideFeign feign;
                      @GetMapping("/hiCall")
                      public String callFeign(){
                          String s = feign.helloFeign();
                          System.out.println(s);
                          System.out.println("消费者获取生产者提供的数据"+s);
                          return s;
                      }
                  

                  注意事项:

                  1. 是一个接口,一个feignClient就对应一个controller地址
                  2. @FeignClient(name=”mall-product”, path=”/product”) name是服务的名称,path是controller

                    上面的requestMapping对应的地址

                  3. 接口中方法的命名不要自己写,从controller中复制过来

                  SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第7张

                  4.controller中直接调用feign

                  SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第8张

                  深入认识feign

                  1.代理对象

                  从上面的feign使用可以知道,ProductFeignClient是一个接口,我们在OrderController中注入的

                  ProductFeignClient不可能是一个接口,肯定是一个实例化的对象。

                  SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第9张

                  2.feign与ribbon的关系

                  Ribbon是一个基于 HTTP 和 TCP 客户端 的负载均衡的工具。它可以 在客户端 配置RibbonServerList(服务端列表),使用 HttpClient 或 RestTemplate 模拟http请求,步骤相当繁琐。

                  Feign 是在 Ribbon的基础上进行了一次改进,是一个使用起来更加方便的 HTTP 客户端。采用接口的方式, 只需要创建一个接口,然后在上面添加注解即可 ,将需要调用的其他服务的方法定义成抽象方法即可, 不需要自己构建http请求。然后就像是调用自身工程的方法调用,而感觉不到是调用远程方法,使得编写客户端变得非常容易。

                  3.fegin的其他配置

                  (1)超时时间

                  消费端进行配置

                  SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第10张

                  feign:
                    # 打开阿里的 sentinel
                    sentinel:
                      enabled: true
                    # 调用生产者的配置
                    client:
                      config:
                        springCloud-provider:
                          connect-timeout: 3000 # 连接超时时间,单位毫秒,默认2秒
                          read-timeout: 3000 # 处理请求的时间,默认是5s
                  

                  生产者进行线程的休眠

                  SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第11张

                      @GetMapping("/hello")
                      public String hello(){
                          String s = "服务"+serverId+",端口:"+port+",电影名:"+movieName;
                          System.out.println(s);
                          try {
                              Thread.sleep(4000); // 生产者休眠4s之后响应
                          } catch (InterruptedException e) {
                              throw new RuntimeException(e);
                          }
                          return s;
                      }
                  

                  消费者调用feign报错500

                  SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第12张

                  (2)请求压缩

                  Spring Cloud Feign 支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。通过下面的参数,即可开启请求与响应的压缩功能:

                  SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第13张

                  feign:
                    # 打开阿里的 sentinel
                    sentinel:
                      enabled: true
                    # 调用生产者的配置
                    client:
                      config:
                        springCloud-provider:
                          connect-timeout: 3000 # 连接超时时间,单位毫秒,默认2秒
                          read-timeout: 3000 # 处理请求的时间,默认是5s
                    compression:
                      request:
                        enabled: true # 开启请求压缩,默认为false
                        # 设置支持压缩的数据类型
                        mime-types: text/html,application/xml,application/json
                        # 设置触发压缩的数据下限
                        min-request-size: 1  # 2048 2M?
                      response:
                        # 开启响应压缩,默认值为false
                        enabled: true
                  

                  SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第14张

                  4.日志级别的配置

                  在开发或者运行阶段往往希望看到Feign请求过程的日志记录,默认情况下Feign的日志是没有开启的。

                  要想用属性配置方式来达到日志效果,只需在 application.yml 中添加如下内容即可:

                  日志级别

                  • NONE:默认的,不显示任何日志
                  • BASIC:仅记录请求方法、RUL、响应状态码及执行时间(在生产环境使用)
                  • HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息
                  • FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据(在开发环境使用)

                    (1)配置文件yml

                    feign:
                      # 打开阿里的 sentinel
                      sentinel:
                        enabled: true
                      # 调用生产者的配置
                      client:
                        config:
                          springCloud-provider:
                            connect-timeout: 3000 # 连接超时时间,单位毫秒,默认2秒
                            read-timeout: 3000 # 处理请求的时间,默认是5s
                            loggerLevel: BASIC # 设置feign调用的日志级别 NONE BASIC HEADERS FULL
                    

                    配置文件的方式配置,只能针对某一个服务起作用,可以使用配置类的方式进行配置

                    (2)配置类配置

                    级别解释
                    NONE默认的,不显示任何日志
                    BASIC仅记录请求方法、URL、响应状态码及执行时间
                    HEADERS除了 BASIC 中定义的信息之外,还有请求和响应的头信息
                    FULL除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据

                    在consumer-feign中添加feign日志配置类,指定日志输出级别以显示指定的内容

                    注意Level的包为:feign.Logger

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第15张

                    package com.tianju.consumer.config;
                    import feign.Logger;
                    import org.springframework.context.annotation.Bean;
                    import org.springframework.context.annotation.Configuration;
                    /**
                     * 定义feign的日志打印级别,作为全局的日志输出控制
                     * @return
                     */
                    @Configuration
                    public class FeignLogConfig {
                        @Bean
                        public Logger.Level level(){
                            return Logger.Level.FULL;
                        }
                    }
                    

                    因为feign日志的输出级别都是debug级别,因此如果想要看到日志信息,还需要设置service包的日志级别

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第16张

                    logging:
                      level:
                        com.tianju.consumer: debug
                    

                    此时再调用就会显示feign的日志

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第17张

                    feign的源码分析

                    通过上面的使用过程,@EnableFeignClients和@FeignClient两个注解就实现了Feign的功能,那我们从

                    @EnableFeignClients注解开始分析Feign的源码

                    1)@EnableFeignClients与@FeignClient

                    通过 @EnableFeignClients 引入了FeignClientsRegistrar客户端注册类

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第18张

                    然后通过registerFeignClient 注册了feign客户端对象

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第19张

                    创建代理对象注册到spring容器中

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第20张

                    工厂模式,生成feign的bean工厂

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第21张

                    创建代理对象

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第22张

                    2)请求的发送拆解

                    FeignClientFactoryBean.getObject()具体返回的是一个代理类,具体为FeignInvocationHandler,调

                    用该类中的invoke方法

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第23张

                    先要找到url

                    先在feign的核心包中,找到生产者的url

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第24张

                    紧着这获取了后面拼的路径

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第25张

                    拿到路径

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第26张

                    两者拼一下,然后把生产者url作为消费者的url的一个子路径请求

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第27张

                    invoke方法执行创建RequestTemplate

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第28张

                    类似于RestTemplat

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第29张

                    执行生产者的调用feign的map,似乎是一个一个调用,获取响应

                    SpringCloud入门(微服务调用 OpenFeign)——从RestTemplate到OpenFeign & OpenFeign的相关配置 & 源码的分析和请求流程拆解,在这里插入图片描述,第30张


                    总结

                    1.spring提供的restTemplate,发送HTTP请求的客户端工具类;

                    2.OpenFeign,声明式的HTTP客户端,用于简化服务间的调用;

                    3.和ribbon的关系,其他的配置,超时时间,日志级别;

                    4.源码分析,@EnableFeignClient和@FeignClient的作用;

                    5.尝试分析OpenFeign请求发送的流程;