学习笔记:
官网地址:https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/#spring-cloud-feign
源码:https://github.com/spring-cloud/spring-cloud-openfeign
1、概念总结
OpenFeign是一个声明式的Web服务客户端,只需创建一个Rest接口并在该接口添加注解@FeignClient即可。
OpenFeign基本上就是当前微服务之间调用的事实标准。
1.1、能干嘛?
(1)可插拔的注解支持,包括Fegign注解和JAX-RS注解
(2)支持可插拔的HTTP编码器和解码器
(3)支持Sentinel和它的Fallback
(4)支持SpringCloudLoadBalancer的负载均衡
(5)支持HTTP请求和响应的压缩
1.2、示例:
2、代码示例
2.1、pom
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.2、yaml
server:
port: 80
spring:
application:
name: cloud-consumer-openfeign-order
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}
2.3、main
@EnableFeignClients //启用feign客户端,定义服务+绑定接口,以声明式的方法优雅而简单的实现服务调用
@EnableDiscoveryClient //该注解用于向使用consul为注册中心时注册服务
@SpringBootApplication
public class OpenFeign80Application {
public static void main(String[] args) {
SpringApplication.run(OpenFeign80Application.class, args);
}
}
2.4、 FeignClient Api
@FeignClient(value = "cloud-payment-service")
public interface PayFeignApi {
/**
* 新增一条支付相关流水记录
* @param payDTO
* @return
*/
@PostMapping("/pay/add")
public ResultData<Object> addPay(@RequestBody PayDTO payDTO);
/**
* 按照主键记录查询支付流水信息
* @param id
* @return
*/
@GetMapping("/pay/get/{id}")
public ResultData<Object> getPayInfo(@PathVariable("id") Integer id);
/**
* openfeign天然支持负载均衡演示
* @return
*/
@GetMapping(value = "/pay/get/info")
public String mylb();
}
2.5、Controller
@RestController
public class OrderController {
@Resource
private PayFeignApi feignApi;
@PostMapping("/feign/pay/add")
public ResultData<Object> addOrder(@RequestBody PayDTO payDTO) {
return feignApi.addPay(payDTO);
}
@GetMapping("/feign/pay/get/{id}")
public ResultData<Object> getPayInfo(@PathVariable("id") Integer id) {
return feignApi.getPayInfo(id);
}
@GetMapping("/feign/pay/get/info")
public String getPayInfoByConsul() {
return feignApi.mylb();
}
}
2.6、测试
###
POST localhost:80/feign/pay/add
Accept: application/json
Content-Type: application/json
{
"payNo":"payfeign123456",
"orderNo":"consumer-feign1",
"userId":"1",
"amount":"8.28"
}
###
GET localhost:80/feign/pay/get/1
###
GET localhost:80/feign/pay/get/info
3、高级特性(*)
3.1、超时控制
在Spring Cloud微服务架构中,大部分公司都是利用OpenFeign进行服务间的调用,而比较简单的业务使用默认配置是不会有多大问题的,但是如果是业务比较复杂,服务要进行比较繁杂的业务计算,那后台很有可能会出现Read Timeout这个异常,因此定制化配置超时时间就有必要了。
默认OpenFeign客户端等待60秒钟,但是服务端处理超过规定时间会导致Feign客户端返回报错。为了避免这样的情况,有时候我们需要设置Feign客户端的超时控制,默认60秒太长或者业务时间太短都不好。
connectTimeout 连接超时时间
readTimeout 请求处理超时时间
3.1.1、服务提供者cloud-provider-payment8001,调用接口添加超时时间bug
@Operation(summary = "根据id查询流水", description = "查询支付流水方法")
@GetMapping("/get/{id}")
public ResultData<Pay> getById(@PathVariable("id") Integer id){
if (id == -4){
throw new RuntimeException("id不能为负数");
}
try {
//暂停62秒,测试feign默认超时时间
TimeUnit.SECONDS.sleep(62);
}catch (InterruptedException e){
e.printStackTrace();
}
Pay payById = payService.getPayById(id);
return ResultData.success(payById);
}
3.1.2、服务调用方cloud-consumer-feign-order80写好捕捉超时异常
@GetMapping("/feign/pay/get/{id}")
public ResultData<Object> getPayInfo(@PathVariable("id") Integer id) {
ResultData<Object> payInfo = null;
try {
System.out.println("调用开始-----:" + DateUtil.now());
payInfo = feignApi.getPayInfo(id);
}catch (Exception e){
e.printStackTrace();
System.out.println("调用结束-----:" + DateUtil.now());
return ResultData.fail(ReturnCodeEnum.RC500.getCode(), e.getMessage());
}
return payInfo;
}
测试结果
结论:OpenFeign默认超时时间60秒,超时报错。
3.1.3、配置
(1)全局配置
关键内容:
spring:
cloud:
openfeign:
client:
config:
default:
#连接超时时间
connectTimeout: 3000
#读取超时时间
readTimeout: 3000
配置文件,改为超时时间为3秒钟
server:
port: 80
spring:
application:
name: cloud-consumer-openfeign-order
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}
openfeign:
client:
config:
default:
#连接超时时间
connect-timeout: 3000
#读取超时时间
read-timeout: 3000
测试结果:
(2)指定配置
配置文件,改为超时时间为5秒钟,区别是将 defalut改为服务名 cloud-payment-service
server:
port: 80
spring:
application:
name: cloud-consumer-openfeign-order
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}
openfeign:
client:
config:
#服务名
cloud-payment-service:
#连接超时时间
connect-timeout: 5000
#读取超时时间
read-timeout: 5000
(3)全局配置和指定配置同时存在
全局配置和指定配置可以同时存在,细粒度的配置生效。
3.2、重试机制
在cloud-consumer-feign-order80添加配置
@Configuration
public class FeignConfig {
@Bean
public Retryer myRetryer() {
// return Retryer.NEVER_RETRY; //默认不走重试策略
//最大请求次数韦 3(1+2),初始时间间隔为100ms,重试最大间隔时间为1s
return new Retryer.Default(100,1,3);
}
}
3.3、性能优化之HttpClient5
(1)默认应用
(2) 替换原因
(3)所需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>
(4)yaml配置,开启httpclient5配置
# Apache HttpClient5 配置开启
spring:
cloud:
openfeign:
httpclient:
hc5:
enabled: true
替换结果
3.4、请求/响应压缩
对请求和响应进行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配置
server:
port: 80
spring:
application:
name: cloud-consumer-openfeign-order
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}
openfeign:
client:
config:
default:
#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
调用结果
3.5、OpenFeign日志打印
Feign 提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解 Feign 中 Http 请求的细节,就是对Feign接口的调用情况进行监控和输出。
(1)日志级别
NONE:默认的,不显示任何日志;
BASIC:仅记录请求方法、URL、响应状态码及执行时间;HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息;FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。
(2)配置日志bean
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
(3)yml配置
公式(三段):logging.level + 含有@FeignClient注解的完整带包名的接口名+debug
# feign日志以什么级别监控哪个接口
logging:
level:
com:
atguigu:
cloud:
apis:
PayFeignApi: debug
server:
port: 80
spring:
application:
name: cloud-consumer-openfeign-order
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}
openfeign:
client:
config:
default:
#连接超时时间
connect-timeout: 3000
#读取超时时间
read-timeout: 3000
httpclient:
hc5:
enabled: true
compression:
request:
enabled: true
min-request-size: 2048 #最小触发压缩的大小
mime-types: text/xml,application/xml,application/json #触发压缩数据类型
response:
enabled: true
# feign日志以什么级别监控哪个接口
logging:
level:
com:
atguigu:
cloud:
apis:
PayFeignApi: debug