Feign

Feign

  • 1 Feign介绍
  • 2 Feign远程调用
    • 2.1 Feign替代RestTemplate
    • 2.2 自定义配置
    • 2.3 Feign使用优化
    • 2.4 最佳实践
  • 总结

1 Feign介绍

Feign是一个声明式的Web服务客户端,它使得编写Web服务客户端变得更加简单。它是Spring Cloud中的一个模块,用于简化对REST服务的调用。使用Feign可以通过简单的接口描述来创建一个HTTP客户端。Feign的主要目标是让远程调用更加简单、编码更少、易于维护。

Feign的核心特性

  • 声明式REST客户端:Feign提供了一种声明式的方法来定义REST客户端,使得服务之间的调用变得非常简洁。

  • 负载均衡:集成了Ribbon,Feign自带客户端负载均衡功能。

  • 容错与断路器:通过集成Hystrix,Feign提供了断路器的支持,增加了服务的容错能力。

  • 易于集成和使用:Feign天然集成于Spring Ecosystem,使其非常容易与Spring Boot应用集成使用。

  • 可插拔的注解支持:Feign支持Spring MVC注解,也支持JAX-RS注解,甚至可以自定义注解。

  • 可定制性:Feign提供了多种可配置的选项,包括编码器、解码器、拦截器等,让你可以根据需求定制Feign的行为。

Feign以其简洁性和强大的功能,成为了微服务架构中进行服务间调用的首选工具。通过使用Feign,可以大大简化远程服务调用的代码,提高开发效率和服务的稳定性。

2 Feign远程调用

先来看我们以前利用RestTemplate发起远程调用的代码:

在这里插入图片描述

存在下面的问题:

  • 代码可读性差,编程体验不统一

  • 参数复杂URL难以维护

Feign是一个声明式的http客户端,官方地址:https://github.com/OpenFeign/feign

其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。

在这里插入图片描述

2.1 Feign替代RestTemplate

Fegin的使用步骤如下:

1)引入依赖

我们在order-service服务的pom文件中引入feign的依赖:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2)添加注解

在order-service的启动类添加注解开启Feign的功能:

在这里插入图片描述

3)编写Feign的客户端

Feign定义接口的方式在某种程度上与Spring MVC中定义Controller很相似,这种相似性主要体现在使用注解来声明请求路径和参数等信息。

  • 都广泛使用注解来定义路由、请求方法和参数绑定等。例如,Feign和Spring MVC都使用@GetMapping@PostMapping等注解来指定HTTP请求的类型。

  • 都支持使用注解来绑定请求参数,比如@RequestParam@PathVariable@RequestBody等。

在order-service中新建一个接口,内容如下:

package cn.cloud.order.client;import cn.cloud.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient("userservice")
public interface UserClient {@GetMapping("/user/{id}")User findById(@PathVariable("id") Long id);
}

这个客户端主要是基于SpringMVC的注解来声明远程调用的信息,比如:

  • 服务名称:userservice
  • 请求方式:GET
  • 请求路径:/user/{id}
  • 请求参数:Long id
  • 返回值类型:User

这样,Feign就可以帮助我们发送http请求,无需自己使用RestTemplate来发送了。

4)测试

修改order-service中的OrderService类中的queryOrderById方法,使用Feign客户端代替RestTemplate:

在这里插入图片描述

是不是看起来优雅多了。

5)总结

使用Feign的步骤:

① 引入依赖

② 添加@EnableFeignClients注解

③ 编写FeignClient接口

④ 使用FeignClient中定义的方法代替RestTemplate

2.2 自定义配置

Feign可以支持很多的自定义配置,如下表所示:

类型作用说明
feign.Logger.Level修改日志级别包含四种不同的级别:NONE、BASIC、HEADERS、FULL
feign.codec.Decoder响应结果的解析器http远程调用的结果做解析,例如解析json字符串为java对象
feign.codec.Encoder请求参数编码将请求参数编码,便于通过http请求发送
feign. Contract支持的注解格式默认是SpringMVC的注解
feign. Retryer失败重试机制请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

一般情况下,默认值就能满足我们使用,如果要自定义时,只需要创建自定义的@Bean覆盖默认Bean即可。

下面以日志为例来演示如何自定义配置。

配置文件方式

基于配置文件修改feign的日志级别可以针对单个服务:

feign:client:config:userservice: # 针对某个微服务的配置loggerLevel: FULL #  日志级别

也可以针对所有服务:

feign:client:config:default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置loggerLevel: FULL #  日志级别

而日志的级别分为四种:

  • NONE:不记录任何日志信息,这是默认值。
  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

Java代码方式

也可以基于Java代码来修改日志级别,先声明一个类,然后声明一个Logger.Level的对象:

public class DefaultFeignConfiguration  {@Beanpublic Logger.Level feignLogLevel(){return Logger.Level.BASIC; // 日志级别为BASIC}
}

如果要全局生效,将其放到启动类的@EnableFeignClients这个注解中:

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)

如果是局部生效,则把它放到对应的@FeignClient这个注解中:

@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)

2.3 Feign使用优化

Feign底层发起http请求,依赖于其它的框架。其底层客户端实现包括:

  • URLConnection:默认实现,不支持连接池

  • Apache HttpClient :支持连接池

  • OKHttp:支持连接池

因此提高Feign的性能主要手段就是使用连接池代替默认的URLConnection。

这里我们用Apache的HttpClient来演示。

1)引入依赖

在order-service的pom文件中引入Apache的HttpClient依赖:

<!--httpClient的依赖 -->
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId>
</dependency>

2)配置连接池

在order-service的application.yml中添加配置:

feign:client:config:default: # default全局的配置loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息httpclient:enabled: true # 开启feign对HttpClient的支持max-connections: 200 # 最大的连接数max-connections-per-route: 50 # 每个路径的最大连接数

接下来,在FeignClientFactoryBean中的loadBalance方法中打断点:

在这里插入图片描述

Debug方式启动order-service服务,可以看到这里的client,底层就是Apache HttpClient:

在这里插入图片描述

总结,Feign的优化:

1.日志级别尽量用basic

2.使用HttpClient或OKHttp代替URLConnection

① 引入feign-httpClient依赖

② 配置文件开启httpClient功能,设置连接池参数

2.4 最佳实践

所谓最近实践,就是使用过程中总结的经验,最好的一种使用方式。

仔细观察可以发现,Feign的客户端与服务提供者的controller代码非常相似:

feign客户端:

在这里插入图片描述

UserController:

在这里插入图片描述

有没有一种办法简化这种重复的代码编写呢?

继承方式

一样的代码可以通过继承来共享:

1)定义一个API接口,利用定义方法,并基于SpringMVC注解做声明。

2)Feign客户端和Controller都集成改接口

在这里插入图片描述

优点:

  • 简单
  • 实现了代码共享

缺点:

  • 服务提供方、服务消费方紧耦合

  • 参数列表中的注解映射并不会继承,因此Controller中必须再次声明方法、参数列表、注解

抽取方式

将Feign的Client抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用。

例如,将UserClient、User、Feign的默认配置都抽取到一个feign-api包中,所有微服务引用该依赖包,即可直接使用。

在这里插入图片描述

实现基于抽取的最佳实践

1)抽取

首先创建一个module,命名为feign-api:

在这里插入图片描述

项目结构:

在这里插入图片描述

在feign-api中然后引入feign的starter依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

然后,order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中

在这里插入图片描述

2)在order-service中使用feign-api

首先,删除order-service中的UserClient、User、DefaultFeignConfiguration等类或接口。

在order-service的pom文件中中引入feign-api的依赖:

<dependency><groupId>cn.cloud.demo</groupId><artifactId>feign-api</artifactId><version>1.0</version>
</dependency>

修改order-service中的所有与上述三个组件有关的导包部分,改成导入feign-api中的包

3)重启测试

重启后,发现服务报错了:

在这里插入图片描述

这是因为UserClient现在在cn.cloud.feign.clients包下,

而order-service的@EnableFeignClients注解是在cn.cloud.order包下,不在同一个包,无法扫描到UserClient。

4)解决扫描包问题

方式一:

指定Feign应该扫描的包:

@EnableFeignClients(basePackages = "cn.cloud.feign.clients")

方式二:

指定需要加载的Client接口:

@EnableFeignClients(clients = {UserClient.class})

最佳实践之自动装配

之前我们的项目都需要使用 @EnableFeignClients 来指定加载的 Feign 客户端。接下来我们将项目进行改进,使其只要引入 feign-api 模块就能实现自动加载

在开始之前将 DefaultFeignConfiguration 修改为 FeignConfig ,进行改造之后这个类的意义也发生了改变。不仅仅是维护一个日志的 bean 对象,而是真正的被看作一个配置类。

1)在 feign-api 模块的 resource 目录下新建目录 META-INF

在这里插入图片描述

2)在 META-INF 目录下新建文件 spring.factories

在这里插入图片描述
3)进入调用 Feign 客户端的启动类那里,找到SpringBoot启动类注解,点进去。

在这里插入图片描述

4)找到 EnableAutoConfiguration 注解点进去,复制它的全限定名。

在这里插入图片描述

package org.springframework.boot.autoconfigure;import ........@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};
}
//这里的全限定名称为  org.springframework.boot.autoconfigure.EnableAutoConfiguration

5)得到 EnableAutoConfiguration 的全限定名称后,将其作为 key 而 FeignConfig 的全限定名称作为 value 写入 spring.factories 文件中。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.cloud.feign.config.FeignConfig 

6)将调用 Feign 客户端的启动类的 @EnableFeignClients 注解删掉,拿到 FeignConfig 上。

在这里插入图片描述

package cn.cloud.feign.config;import feign.Logger;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author shenyang* @version 1.0* @Date 2024/3/17 11:42*/
@Configuration
@EnableFeignClients(basePackages = "cn.cloud.feign.clients")//开启feign功能支持,自动扫描 main启动类下的同级或者一切子目录下的feign客户端资源
public class FeignConfig {@Beanpublic Logger.Level loggerLevel() {return Logger.Level.BASIC;}
}

在这里插入图片描述

最后测试一下,可以发现,访问成功。

总结

在本文中,我们深入探讨了Feign——一个声明式的Web服务客户端,它作为Spring Cloud生态系统中的一个重要组成部分,极大地简化了微服务架构下服务间的HTTP调用。通过Feign,开发者可以以最少的努力实现服务之间的通信,这得益于它的声明式编程模型、集成的负载均衡、断路器支持以及与Spring生态系统的无缝集成。

我们讨论了Feign的工作原理、如何使用Feign、以及它的核心特性,这些内容为理解Feign提供了一个全面的视角。通过比较Feign与Spring MVC的定义方式,我们看到了两者之间的相似性和差异性,这不仅凸显了Feign在微服务通信方面的专注和高效,也展示了Spring生态系统内不同组件之间设计哲学的一致性和互补性。

总结而言,Feign是微服务架构中进行服务间调用的理想选择,它通过简化远程调用的复杂性,使得开发者可以更专注于业务逻辑的实现。随着微服务架构的日益普及,掌握Feign将成为每个Spring开发者的重要技能之一。希望这篇博客能够帮助你更好地理解Feign,为你的微服务旅程添砖加瓦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/549017.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Leetcode-19.删除链表的第N个节点】

题目详情&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1…

中国巨型地下中微子实验室准备探究宇宙奥秘

JUNO设施将于今年上线&#xff0c;将有助于确定哪种类型的中微子质量最高 - 这是物理学中最大的谜团之一。 中国江门地下中微子天文台&#xff08;JUNO&#xff09;的建设工作。朱诺号希望在2024年底之前探测到中微子。图片来源&#xff1a;Qiu Xinsheng/VCG via Getty 开平区…

SpringBoot ApplicationListener实现发布订阅模式

文章目录 前言一、Spring对JDK的扩展二、快速实现发布订阅模式 前言 发布订阅模式(Publish-Subscribe Pattern)通常又称观察者模式&#xff0c;它被广泛应用于事件驱动架构中。即一个事件的发布&#xff0c;该行为会通过同步或者异步的方式告知给订阅该事件的订阅者。JDK中提供…

SQ—inner join、left join、right join区别

关联表查询常用关键字join 假设现有两张表&#xff1a;subject和score left join 基表&#xff1a;左表 表1左连接表2&#xff0c;以左为主&#xff0c;表示以表1为主&#xff0c;关联上表2的数据&#xff0c;查出来的结果显示左边的所有数据&#xff0c;然后右边显示的是和…

2024全新红娘交友系统定制版源码 | 相亲交友小程序源码 全开源可二开

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 全新红娘交友系统定制版源码 | 相亲交友小程序源码 全开源可二开 定制版红娘交友平台小程序源码&#xff0c;很牛逼的东西&#xff0c;虽然是小程序&#xff0c;但是有700多M大&…

10大漏洞评估和渗透测试工具【附安装包】

1、Netsparker Security Scanner 专为企业设计的强大的漏洞扫描和管理工具&#xff0c;它可以检测和利用 SQL 注入和 XSS 等漏洞。 https://www.netsparker.com/product/ 2、Acunetix Scanner 针对中小型企业的 Web 应用程序漏洞扫描程序&#xff0c;但也可以扩展到更大的组…

zabbix企业微信接入结合海螺问问编写的shell脚本

前言 博客懒得写详细了&#xff0c;视频剪的累死了&#xff0c;看视频就好了 白帽小丑的个人空间-白帽小丑个人主页-哔哩哔哩视频 shell脚本 #!/bin/bash #set -x CorpID"" #我的企业下面的CorpID Secret"" #创建的应用那…

旅行社旅游线路预定管理系统asp.net

旅行社旅游线路预定管理系统 首页 国内游 境外游 旅游景点 新闻资讯 酒店信息―留言板 后台管理 后台管理导航菜单系统管理修改密码留言管理注册会员管理基础数据设置国别设置有份设地区设置 旅行社管理友情链接管理添加友情链接友情链接管理新闻资讯管理添加新闻资讯新闻资讯管…

Java语法学习八之认识String类

String类的重要性 在C语言中已经涉及到字符串了&#xff0c;但是在C语言中要表示字符串只能使用字符数组或者字符指针&#xff0c;可以使用标准库提供的字符串系列函数完成大部分操作&#xff0c;但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想&#xff0c;而…

Python和R的区别是什么,Python与R的应用场景是什么?

如果你这么问&#xff0c;那么你可能正站在数据科学的起点。对于志在成为数据专业人员的你来说&#xff0c;学习编程是无疑的。我想行你早就听过Python 与R的比较之声&#xff0c;并在选择中感到困惑。在此&#xff0c;我想说&#xff0c;也算是一种安慰吧&#xff1a;对于语言…

蓝桥杯练习01卡片化标签

卡片化标签页 介绍 选项卡功能在前端开发中特别常见&#xff0c;作为设置选项的模块&#xff0c;每个选项卡代表一个活动的区域&#xff0c;点击不同的区域&#xff0c;即可展现不同的内容&#xff0c;这样既能节约页面的空间又能提升页面性能。 本题需要在已提供的基础项目中…

【系统架构师】-第19章-大数据架构设计理论与实践

四个特点&#xff1a; 大规模&#xff08;Volume&#xff09;、高速度&#xff08;Velocity&#xff09;和多样化&#xff08;Variety&#xff09;&#xff0c;价值&#xff08;Value&#xff09;。 五个问题&#xff1a; 异构性&#xff08;Heterogeneity&#xff09;、规模…