简单理解Feign的原理与使用

article/2025/9/2 13:36:13

文章目录

  • SpringCloud 总架构图
  • 一、简介
    • 1.1、负载均衡的概念
    • 2.2、Feign概念
  • 二、入门案例
    • 2.1、导入依赖
    • 2.2、Feign的客户端
    • 2.3、调用Feign
    • 2.4、开启Feign功能
    • 2.5、启动测试
    • 2.6、Feign实现原理简单分析
  • 三、负载均衡(Ribbon)
  • 四、熔断器支持
  • 五、请求压缩和响应压缩
  • 六、配置日志级别


SpringCloud 总架构图

请添加图片描述

Spring Cloud 常见的集成方式是使用Feign+Ribbon技术来完成服务间远程调用及负载均衡的,如下图

在这里插入图片描述

  1. 在微服务启动时,会向服务发现中心上报自身实例信息,这里ServiceB 包含多个实例。 每个实例包括:IP地址、端口号信息。

  2. 微服务会定期从Nacos Server(服务发现中心)获取服务实例列表。

  3. 当ServiceA调用ServiceB时,ribbon组件从本地服务实例列表中查找ServiceB的实例,如获取了多个实例如:Instance1、Instance2。这时ribbon会通过用户所配置的负载均衡策略从中选择一个实例。

  4. 最终,Feign组件会通过ribbon选取的实例发送http请求。

采用Feign+Ribbon的整合方式,是由Feign完成远程调用的整个流程。而Feign集成了Ribbon,Feign使用Ribbon

完成调用实例的负载均衡。

一、简介

1.1、负载均衡的概念

在SpringCloud服务协议流程中,ServiceA通过负载均衡调用ServiceB,下边来了解一下负载均衡

负载均衡就是将用户请求(流量)通过一定的策略,分摊在多个服务实例上执行,它是系统处理高并发、缓解网络

压力和进行服务端扩容的重要手段之一。它分为服务端负载均衡客户端负载均衡

服务器端负载均衡:

在这里插入图片描述

客户端负载均衡:

在这里插入图片描述

2.2、Feign概念

Feign 的英文表意为“假装,伪装,变形”, 是一个http请求调用的轻量级框架,是以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,这种请求相对而言比较直观。

Feign被广泛应用在Spring Cloud 的解决方案中,是学习基于Spring Cloud 微服务架构不可或缺的重要组件。

**封装了Http调用流程,更符合面向接口化的编程习惯。**类似Dubbo服务调用。

项目主页:https://github.com/OpenFeign/feign

二、入门案例

使用Feign替代RestTemplate发送Rest请求。使之更符合面向接口化的编程习惯。

实现步骤:

  1. 导入feign依赖starter
  2. 编写Feign客户端接口
  3. 消费者启动引导类开启Feign功能注解
  4. 访问接口测试

实现过程:

2.1、导入依赖

  • 在consumer-service中添加spring-cloud-starter-openfeign依赖

  • <!--配置feign-->
    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    

2.2、Feign的客户端

  • 在consumer-service中编写Feign客户端接口类ConsumerService

  • @FeignClient(value = "provider-service")
    public interface ConsumerService {//String url = String.format("http://provider-service/user/findUserById/%s",id);@RequestMapping("/user/findUserById/{id}")User findUserById(@PathVariable("id") Integer id);}
    
    • Feign会通过动态代理,帮我们生成实现类。
    • 注解@FeignClient声明Feign的客户端,指明服务名称
    • 接口定义的方法,采用SpringMVC的注解。Feign会根据注解帮我们生成URL地址

2.3、调用Feign

  • 编写ConsumerFeignController,使用ConsumerService访问

    • @Autowired注入ConsumerService

    • @RestController
      @RequestMapping("/consumer")
      public class ConsumerController {@Autowiredprivate ConsumerService consumerService;@GetMapping("/findUserById/{id}")public User findUserById(@PathVariable Integer id){return consumerService.findUserById(id);}}
      

2.4、开启Feign功能

  • 在ConsumerApplication启动类上,添加@EnableFeignClients注解,开启Feign功能

    @SpringBootApplication
    @EnableFeignClients  //开启feign
    @EnableDiscoveryClient
    public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class,args);}
    }
    

2.5、启动测试

访问接口http://localhost:8081/consumer/findUserById/1,正常获取结果:

在这里插入图片描述

2.6、Feign实现原理简单分析

在这里插入图片描述

Feign帮我们做了哪些事儿:

  • 在 声明Feign客户端 之后,Feign会根据@FeignClient注解使用java的动态代理技术生成代理类,在这里我们指定@FeignClient value为serviceB,则说明这个类的远程目标为spring cloud的服务名称为serviceB的微服务。

  • serviceB的具体访问地址,Feign会交由ribbon获取,若该服务有多个实例地址,ribbon会采用指定的负载均衡策略选取实例。

  • Feign兼容spring的web注解(如:@GetMapping),它会分析声明Feign客户端方法中的Spring注解,得出Http请求method、参数信息以及返回信息结构。

  • 当业务调用Feign客户端方法时,会调用代理类,根据以上分析结果,由代理类完成实际的参数封装、远程http请求,返回结果封装等操作。

三、负载均衡(Ribbon)

Feign本身集成了Ribbon,因此不需要额外引入依赖。在这里插入图片描述

Ribbon是一个客户端负载均衡器,它的责任是从一组实例列表中挑选合适的实例,如何挑选?取决于负载均衡策

Ribbon核心组件IRule是负载均衡策略接口,它有如下实现,大家仅做了解:

  • RoundRobinRule(默认):轮询,即按一定的顺序轮换获取实例的地址。

  • RandomRule:随机,即以随机的方式获取实例的地址。

  • AvailabilityFilteringRule: 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,以及并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问;

  • WeightedResponseTimeRule: 根据平均响应时间计算所有服务的权重,响应时间越快,服务权重越大,被选中的机率越高; 刚启动时,如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够时,会切换到WeightedResponseTimeRule

  • RetryRule: 先按照RoundRobinRule的策略获取服务,如果获取服务失败,则在指定时间内会进行重试,获取可用的服务;

  • BestAvailableRule: 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务;

  • ZoneAvoidanceRule: 默认规则,复合判断server所在区域的性能和server的可用性选择服务器;

可通过下面方式在spring boot 配置文件中修改默认的负载均衡策略:

account‐service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule 

account-service 是调用的服务的名称,后面的组成部分是固定的。

四、熔断器支持

Feign本身也集成Hystrix熔断器,starter内查看。在这里插入图片描述

服务降级方法实现步骤:

  1. 在配置文件application.yml中开启feign熔断器支持
  2. 编写FallBack处理类,实现FeignClient客户端
  3. 在@FeignClient注解中,指定FallBack处理类。
  4. 测试服务降级效果

实现过程:

  1. 在配置文件application.yml中开启feign熔断器支持:默认关闭

    feign:hystrix:enabled: true # 开启Feign的熔断功能
    
  2. 定义一个类ConsumerServiceImpl,实现刚才编写的ConsumerService,作为FallBack的处理类

    @Component
    public class ConsumerServiceImpl implements ConsumerService {//熔断方法@Overridepublic User findUserById(Integer id) {User user = new User();user.setId(id);user.setNote("网络异常,请稍后再试...");return user;}
    }
    
  3. 在@FeignClient注解中,指定FallBack处理类。。

    @FeignClient(value = "provider-service",fallback = ConsumerServiceImpl.class)
    public interface ConsumerService {//String url = String.format("http://provider-service/user/findUserById/%s",id);@RequestMapping("/user/findUserById/{id}")User findUserById(@PathVariable("id") Integer id);}
    
  4. 重启测试:关闭provider-service服务,然后在页面访问;http://localhost:8081/consumer/findUserById/1

五、请求压缩和响应压缩

SpringCloudFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。

通过配置开启请求与响应的压缩功能:

feign:compression:request:enabled: true # 开启请求压缩response:enabled: true # 开启响应压缩

也可以对请求的数据类型,以及触发压缩的大小下限进行设置

#  Feign配置
feign:compression:request:enabled: true # 开启请求压缩mime-types:	text/html,application/xml,application/json # 设置压缩的数据类型min-request-size: 2048 # 设置触发压缩的大小下限#以上数据类型,压缩大小下限均为默认值

六、配置日志级别

在发送和接收请求的时候,Feign定义了日志的输出定义了四个等级:这里我们配置测试一下。

级别说明
NONE不做任何记录
BASIC只记录输出Http 方法名称、请求URL、返回状态码和执行时间
HEADERS记录输出Http 方法名称、请求URL、返回状态码和执行时间 和 Header 信息
FULL记录Request 和Response的Header,Body和一些请求元数据

实现步骤:

  1. 在application.yml配置文件中开启日志级别配置
  2. 编写配置类,定义日志级别bean。
  3. 在接口的@FeignClient中指定配置类
  4. 重启项目,测试访问

实现过程:

  1. 在consumer-service的配置文件中设置com.itheima包下的日志级别都为debug

    • # com.itheima 包下的日志级别都为Debug
      logging:level:com.itheima: debug
      
  2. 在consumer-service编写配置类,定义日志级别

    • @Configuration
      public class FeignLogLevleConfig {//采用full打印日志@Beanpublic Logger.Level configLog(){return Logger.Level.FULL;}
      }
      
  3. 在consumer-service的ConsumerService中指定配置类

    • @FeignClient(value = "provider-service",fallback = ConsumerServiceImpl.class,configuration = FeignLogLevleConfig.class)
      public interface ConsumerService {@RequestMapping("/user/findUserById/{id}")User findUserById(@PathVariable("id") Integer id);}
      
  4. 重启项目,即可看到每次访问的日志

    • 在这里插入图片描述

http://chatgpt.dhexx.cn/article/SJOqj7mO.shtml

相关文章

【第四章】详解Feign的实现原理

1.1 Feign概述 这篇文章主要讲述如何通过Feign去消费服务&#xff0c;以及Feign的实现原理的解析。 Feign是Netflix开发的声明式、模板化的HTTP客户端&#xff0c;Feign可以帮助我们更快捷、优雅地调用HTTP API。 Feign是⼀个HTTP请求的轻量级客户端框架。通过 接口 注解的…

Feign底层原理分析-自动装载动态代理

本篇文章仅介绍Feign的核心机制&#xff0c;包括如何交由Spring容器托管、动态代理机制等内容&#xff0c;不会过分深入细节。 1、什么是Feign&#xff1f; 这里套用Feign官方Github上的介绍&#xff1a;“Feign是一个灵感来自于Retrofit、JAXRS-2.0、WebSocket的Java Http客户…

Feign原理 (图解)

1.1 简介&#xff1a;Feign远程调用的 Feign远程调用&#xff0c;核心就是通过一系列的封装和处理&#xff0c;将以JAVA注解的方式定义的远程调用API接口&#xff0c;最终转换成HTTP的请求形式&#xff0c;然后将HTTP的请求的响应结果&#xff0c;解码成JAVA Bean&#xff0c;放…

Feign的工作原理

Feign的工作原理 Feign是一个伪Java Http 客户端&#xff0c;Feign 不做任何的请求处理。Feign 通过处理注解生成Request模板&#xff0c;从而简化了Http API 的开发。开发人员可以使用注解的方式定制Request API模板。 在发送Http Request请求之前&#xff0c;Feign通过处理…

Linux命令——tar与gzip详解:文件的打包压缩与解压缩解打包

Linux系统中&#xff0c;最常用的打包命令就是tar了&#xff0c;不仅如此&#xff0c;tar命令还可以解打包解压缩&#xff0c;十分方便。如果单纯想压缩文件&#xff0c;就需要我们的gzip命令了。 使用tar打包归档的包叫做tar包&#xff0c;以.tar结尾 使用gzip压缩的文件&…

Linux 下使用 tar 命令打包指定目录下的所有文件,不包括目录

一&#xff0c;问题描述 无论是 Linux 系统&#xff0c;还是 macOS 系统&#xff0c;我们都可以使用 tar 命令进行文件的压缩打包。命令格式如下&#xff1a; # tar cvf xxxx.tar 要压缩的文件或目录名称但如果要压缩的目录层级比较多时&#xff0c;比如&#xff1a; # tar cvf…

linux tar (打包、压缩、解压)命令

打包程序&#xff1a;tar c: 创建文档t&#xff1a; 列出存档内容x&#xff1a;提取存档f&#xff1a; filename 要操作的文档名v&#xff1a;详细信息 一&#xff1a;打包 打包&#xff1a;是指把文件整合在一起&#xff0c;不压缩 1.将文件打包&#xff1a;tar cf a.ta…

(21)tar打包命令详解

Linux 系统中,最常用的归档(打包)命令就是 tar,该命令可以将许多文件一起保存到一个单独的磁盘中进行归档。不仅如此,该命令还可以从归档文件中还原所需文件,也就是打包的反过程,称为解打包。1.tar命令做打包操作  当 tar 命令用于打包操作时,该命令的基本格式为: …

vector中删除某个指定元素

class Solution { public:int removeElement(vector<int>& v, int val) {for (auto it v.begin(); it ! v.end(); it) {if (*it val) { // 条件语句v.erase(it); // 移除他it--; // 让该迭代器指向前一个}}return v.size();} };

vector删除指定元素

C vector中实际删除元素使用的是容器vecrot中std::vector::erase()方法。 C 中std::remove()并不删除元素&#xff0c;因为容器的size()没有变化&#xff0c;只是元素的替换。 1.std::vector::erase() 函数原型&#xff1a;iterator erase (iterator position);  //删除指定…

C++中vector中删除/添加指定位置处的元素

1、函数介绍 C中vector容器可以删除/添加制定位置处的元素&#xff0c;分别使用erase()与insert()函数。其中函数内需要两个参数&#xff0c;第一个为指定删除/添加的位置&#xff0c;第二个元素为删除/添加的元素值。 iterator insert(const_iterator _Where, _Ty&&…

C/C++ vector 删除指定元素

C vector 删除符合条件的元素C vector中实际删除元素使用的是容器vecrot中std::vector::erase()方法。C 中std::remove()并不删除元素&#xff0c;因为容器的size()没有变化&#xff0c;只是元素的替换。1.std::vector::erase()  函数原型&#xff1a;iterator erase (iterat…

【c++】vector中删除元素

目录 1.删除指定范围的元素2.删除指定大小的元素3.C20 std::erase, std::erase_if (std::vector)注意点 1.删除指定范围的元素 vector删除元素之pop_back(),erase(),remove() 向量容器vector的成员函数pop_back()可以删除最后一个元素. 而函数erase()可以删除由一个iterator指…

光纤光学原理相关基础知识点

记&#xff1a;研究生导师的方向是光纤光学和机器学习交叉的&#xff0c;导师给推荐了本书&#xff0c;书里面的理论和推导公式作为小白的我真的是不太行&#xff0c;后来在中国大学mooc上找了视频课跟着学习&#xff0c;顺便做下笔记&#xff0c;为日后使用&#xff0c;因此会…

机器人学重点知识点总结

机器人学重点知识点总结 坐标转换与机械臂运动学雅克比矩阵机械臂逆向动力学&#xff08;牛顿欧拉递推&#xff09;机械臂正向动力学运动轨迹生成动力学轨迹跟踪控制 这篇博客主要用来记录一下现代机器人学里面比较基础也比较重要的一些知识点&#xff0c;所有内容均仅仅记录是…

大学物理(下)知识点总结

大学物理&#xff08;下&#xff09;知识点总结&#xff08;持续更新&#xff09; 文章目录 大学物理&#xff08;下&#xff09;知识点总结&#xff08;持续更新&#xff09;静电场知识点总结习题精选 磁场知识点总结习题精选 期中复习总结电磁场知识点总结习题精选 狭义相对论…

Lumerical官方案例、FDTD时域有限差分法仿真学习(二)——宽带光栅耦合器(Broadband grating coupler (2D))

这个 2D FDTD 示例展示了如何获得光栅耦合器的宽带特性&#xff0c;并将结果与实验数据进行比较。 此外&#xff0c;该应用示例演示了多频波束计算的正确使用和优势&#xff0c;并将结果与标准单频波束计算进行了比较。 要更好地了解单频和多频波束计算之间的差异&#xff0c;请…

三维计算机视觉(四)--关键点

关键点又称为感兴趣的点&#xff0c;是低层次视觉通往高层次视觉的捷径&#xff0c;抑或是高层次感知对低层次处理手段的妥协。 RangeImage 1.关键点&#xff0c;线&#xff0c;面 关键点特征点&#xff1b; 关键线边缘&#xff1b; 关键面foreground&#xff1b; 上述三个概…

信号完整性基础04:串扰(1)

说在开头&#xff1a;关于x射线&#xff08;2&#xff09; 1895年11月8日&#xff0c;德国维尔茨堡大学的一间实验室里&#xff0c;校长伦琴正在做克鲁克斯管实验&#xff0c;当时房间没开灯&#xff0c;屋子里一片漆黑&#xff0c;放电管用黑纸包得很严实&#xff0c;他突然发…

基于地平面的单目视觉里程计绝对尺度估计

点击上方“3D视觉工坊”&#xff0c;选择“星标” 干货第一时间送达 ●论文摘要 对于基于单目相机的系统来说&#xff0c;从单目相机中恢复绝对度量尺度是一个具有挑战性的问题。利用有限的已知条件&#xff0c;提出了多种尺度估计方法&#xff0c;如根据相机的高度、物体大小等…