官网地址:https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/#spring-cloud-feign
GitHub地址:https://github.com/spring-cloud/spring-cloud-openfeign
本文SpringCloud版本为:
<spring.boot.version>3.1.7</spring.boot.version>
<spring.cloud.version>2022.0.4</spring.cloud.version>
【1】概述
OpenFeign是一个声明性web服务客户端。它使编写web服务客户端变得更容易。使用OpenFeign创建一个接口并对其进行注释。它具有可插入的注释支持,包括OpenFeign注释和JAX-RS注释。OpenFeign还支持可插拔编码器和解码器。
Spring Cloud添加了对Spring MVC注释的支持,以及对使用Spring Web中默认使用的HttpMessageConverter的支持。
Spring Cloud集成了Eureka、Spring Cloud CircuitBreaker以及Spring Cloud LoadBalancer,以便在使用OpenFeign时提供负载平衡的http客户端。
与Feign的区别
Feign
和 OpenFeign
都是用于微服务架构中的声明式HTTP客户端,它们允许开发者以一种简单且类型安全的方式来定义HTTP API客户端。然而,它们之间存在一些关键性的区别,主要体现在以下方面:
起源与归属
- Feign 最初由Netflix开发,是Netflix OSS(Open Source Software)套件的一部分,用于简化客户端对服务端接口的调用,特别适合于Spring Cloud环境。
- OpenFeign 是Spring Cloud团队在Feign的基础上进行的扩展和封装,以便更好地融入Spring Cloud生态系统,尤其是在Spring Boot 2.0及更高版本中。
依赖管理
- Feign 使用的依赖是
spring-cloud-starter-feign
。 - OpenFeign 使用的依赖是
spring-cloud-starter-openfeign
。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
注解支持
- Feign 直接在接口上使用其自身的注解,如
@FeignClient
和@RequestMapping
等,但这些注解的使用方式与Spring MVC的注解有所不同。 - OpenFeign 支持标准的Spring MVC注解,如
@GetMapping
,@PostMapping
等,这使得它可以无缝地集成到Spring MVC的框架中。
版本兼容性
- Feign 可能在Spring Boot较新版本中支持不佳或需要额外配置,因为它的设计更早,可能没有考虑到Spring Boot后续的变化。
- OpenFeign 是为了适应Spring Boot 2.0及以后版本的改进而设计的,因此在新的Spring Boot项目中使用更加推荐。
社区支持与更新
- OpenFeign 作为Spring Cloud官方维护的项目,通常会有更好的文档、示例和社区支持,以及更频繁的更新和bug修复。
总结
OpenFeign可以看作是Feign的进化版本,它修正了一些Feign的不足,并且更加紧密地集成了Spring Boot和Spring Cloud的特性。如果你正在构建一个新的项目或者你正在使用的Spring Boot版本高于2.0,那么使用OpenFeign会是一个更佳的选择。
【2】应用实践
① pom依赖
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
② 服务接口
如下所示,接口上面使用@FeignClient注解并指定了远程服务实例名字。
@FeignClient(value = "cloud-payment-service")
public interface PayFeignApi
{
/**
* 新增一条支付相关流水记录
* @param payDTO
* @return
*/
@PostMapping(value = "/pay/add")
ResultData addPay(@RequestBody PayDTO payDTO);
//...
}
③ 主启动类
这里使用@EnableFeignClients注解
@SpringBootApplication
@EnableDiscoveryClient //该注解用于向使用consul为注册中心时注册服务
@EnableFeignClients//启用feign客户端,定义服务+绑定接口,以声明式的方法优雅而简单的实现服务调用
public class MainOpenFeign80
{
public static void main(String[] args)
{
SpringApplication.run(MainOpenFeign80.class,args);
}
}
如此即可实现服务实例的远程调用,抛弃了RestTemplate+@LoadBalanced,更加优雅简洁。
【3】超时控制
默认OpenFeign客户端等待60秒钟,但是服务端处理超过规定时间会导致Feign客户端返回报错。
① 全局设置
spring:
cloud:
openfeign:
client:
config:
default:
#连接超时时间
connectTimeout: 3000
#读取超时时间
readTimeout: 3000
② 指定服务实例配置
如下这里为服务实例cloud-payment-service设置为2秒。
spring:
cloud:
openfeign:
client:
config:
default:
#连接超时时间
connectTimeout: 3000
#读取超时时间
readTimeout: 3000
cloud-payment-service:
#连接超时时间
connectTimeout: 20000
#读取超时时间
readTimeout: 20000
【4】日志打印功能
Feign 提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解 Feign 中 Http 请求的细节,说白了就是对Feign接口的调用情况进行监控和输出。
① 日志级别
NONE:默认的,不显示任何日志;
BASIC:仅记录请求方法、URL、响应状态码及执行时间;
HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息;
FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。
② 配置类
@Configuration
public class FeignConfig
{
@Bean
Logger.Level feignLoggerLevel()
{
return Logger.Level.FULL;
}
}
③ yml指定接口日志级别
# feign日志以什么级别监控哪个接口
logging:
level:
com:
jane:
cloud:
apis:
PayFeignApi: debug
【5】重试机制
默认重试是关闭的,给了默认值:Retryer.NEVER_RETRY
。
如下所示可以开启重试机制,最大请求三次(第一次请求失败后重试两次)。
@Bean
public Retryer myRetryer()
{
// return Retryer.NEVER_RETRY; //Feign默认配置是不走重试策略的
//最大请求次数为3(1+2),初始间隔时间为100ms,重试间最大间隔时间为1s
return new Retryer.Default(100,1,3);
}
cloud-payment-service侧接口设置等待60秒钟,让consumer调用超时,来查看重试结果。
spring:
application:
name: cloud-consumer-openfeign-order
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}
openfeign:
client:
config:
default:
#连接超时时间
connectTimeout: 3000
#读取超时时间
readTimeout: 3000
cloud-payment-service:
#连接超时时间
connectTimeout: 4000
#读取超时时间
readTimeout: 4000
第一次
第二次
第三次
三次总计耗时12秒,
2024-07-01T10:38:33.505+08:00 DEBUG 21208 --- [p-nio-80-exec-7] com.atguigu.cloud.apis.PayFeignApi : [PayFeignApi#getPayInfo] <--- END ERROR
调用结束-----: 2024-07-01 10:38:33
【6】OpenFeign默认HttpClient修改
OpenFeign中http client如果不做特殊配置,OpenFeign默认使用JDK自带的HttpURLConnection发送HTTP请求。由于默认HttpURLConnection没有连接池、性能和效率比较低,故而可以选择Apache HttpClient 5替换OpenFeign默认的HttpURLConnection。
pom依赖
<!-- httpclient5-->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3</version>
</dependency>
<!-- feign-hc5-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-hc5</artifactId>
<version>13.1</version>
</dependency>
yml开启配置
# Apache HttpClient5 配置开启
spring:
cloud:
openfeign:
httpclient:
hc5:
enabled: true
此时完整格式如下:
spring:
application:
name: cloud-consumer-openfeign-order
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}
openfeign:
client:
config:
default:
#连接超时时间
connectTimeout: 3000
#读取超时时间
readTimeout: 3000
cloud-payment-service:
#连接超时时间
connectTimeout: 4000
#读取超时时间
readTimeout: 4000
httpclient:
hc5:
enabled: true
控制台日志可以看到替换后的效果:
【7】OpenFeign请求/响应压缩
对请求和响应进行GZIP压缩
Spring Cloud OpenFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。通过下面的两个参数设置,就能开启请求与相应的压缩功能:
spring.cloud.openfeign.compression.request.enabled=true
spring.cloud.openfeign.compression.response.enabled=true
细粒度化设置
对请求压缩做一些更细致的设置,比如下面的配置内容指定压缩的请求数据类型并设置了请求压缩的大小下限,只有超过这个大小的请求才会进行压缩:
spring.cloud.openfeign.compression.request.enabled=true
spring.cloud.openfeign.compression.request.mime-types=text/xml,application/xml,application/json #触发压缩数据类型
spring.cloud.openfeign.compression.request.min-request-size=2048 #最小触发压缩的大小
yml文件修改如下:
spring:
application:
name: cloud-consumer-openfeign-order
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}
openfeign:
client:
config:
default:
#连接超时时间
connectTimeout: 3000
#读取超时时间
readTimeout: 3000
cloud-payment-service:
#连接超时时间
connectTimeout: 4000
#读取超时时间
readTimeout: 4000
httpclient:
hc5:
enabled: true
compression:
request:
enabled: true
min-request-size: 2048 #最小触发压缩的大小
mime-types: text/xml,application/xml,application/json #触发压缩数据类型
response:
enabled: true
如下是开启压缩后的效果图: