- OpenFeign是一种声明式RESTful风格的HTTP客户端,同时支持SpringMVC的注解;
- 本篇记录下OpenFeign在工作中常用的知识点;
实现失败降级
OpenFeign 自带熔断器(失败降级),但默认是关闭的,可以在配置中开启:
#开启熔断器
feign:
hystrix:
enabled: true
案例
// 推荐使用 fallbackFactory 可以打印堆栈信息
@FeignClient(name = "user",url = "${user.url}",fallbackFactory = UserFeignFactory.class)
public interface UserFeign {
@GetMapping("/{id}")
User getUserByID(@PathVariable("id") String id);
}
public class UserFeignFactory implements FallbackFactory<UserFeign> {
@Override
public ProducerFeign create(Throwable throwable) {
return id -> {
log.info("错误是:{}", throwable.getMessage());
String msg = "fallback限流方法";
return id + msg;
};
}
}
请求超时时间问题
- OpenFeign的默认请求服务的时间1秒,如果一秒内不能请求到结果则会返回请求超时的错误;
- 如果同时配置Ribbon与OpenFeign的超时时间,那么OpenFeign优先级高;
feign:
client:
config:
pay-service: # 对服务提供者(优先级高):填对应服务提供者名称,
# 对所有提供者(优先级低):固定"default"
connectTimeout: 3000 # 连接超时时间单位ms
readTimeout: 8000 # 读取超时时间单位ms
ribbon:
ReadTimeout: 60000 #ribbon连接超时
ConnectTimeout: 60000 #ribbon读取超时
服务级别设置超时时间
- 可能某些服务确实响应比较慢,设置全局超时时间会出现问题,这时可以设置指定服务设置超时时间;
- 格式为:
{服务名}:ribbon.ConnectTimeout=500
调用请求注意点
- 虽说OpenFeign是支持SpringMVC注解的;
- 在SpringMVC,参数会根据名称作为默认值;
- 但是在OpenFeign中,是必须要显示的声明,不然会报
IllegalStateException
异常:
Caused by: java.lang.IllegalStateException: RequestParam. value() was empty on parameter 0 at feign.Util.checkState(Util.java: 128)
OpenFeign请求重试机制
- OpenFeign默认实现了请求的重试机制;
- 并非所有的异常都会触发重试策略,只有
RetryableException
异常才会触发异常策略; - 在默认Feign配置情况下,只有在网络调用时发生
IOException
异常时,才会抛出RetryableException
,也是就是说链接超时、读超时等不不会触发此异常; - 可以根据
FeignClient
纬度自定义重试策略;
请求压缩配置
- OpenFeign支持对请求与响应进行 GZIP压缩,以减少通信过程中的性能损耗;
- 开启配置:
feign:
compression:
response:
enabled: true
日志级别配置
- OpenFeign 客户端默认的 Logger.Level 对象定义为
NONE
级别, 该级别不会记录任何调用过程中的信息; - 对于 Feign 的 Logger级别主要有下面 4 类, 可根据实际需要进行调整使用:
- NONE:不记录任何信息;
- BASIC:仅记录请求方法、URL以及响应状态码和执行时间;
- HEADERS:除了记录BASIC级别的信息之外, 还会记录请求和响应的头信息;
- FULL:记录所有请求与响应的明细, 包括头信息、 请求体、 元数据等;
配置日志级别比较灵活,可以全局、根据指定FeignClient配置,也可以根据指定服务名进行配置,首先要在yml配置文件中配置日志级别:
feign:
client:
config:
default:
loggerLevel: FULL
全局日志级别配置
@Configuration
public class FeignConfig {
@Bean
public Logger.Level level() {
return Logger.Level.FULL;
}
}
局部日志级别配置
// configuration 指定配置类
@FeignClient(name = "user",url = "${user.url}", configuration = FeignConfig.class)
public interface UserFeign {
@GetMapping("/{id}")
User getUserByID(@PathVariable("id") String id);
}