Feign简介
Feign 是一个声明式的伪RPC的REST客户端,它用了基于接口的注解方式,很方便的客户端配置,刚开始使用时还不习惯,感觉是在客户端写服务端的代码,Spring Cloud 给 Feign 添加了支持Spring MVC注解,并整合Ribbon及Eureka进行支持负载均衡。
如何使用Feign
在前面的博客中,我们已经使用过了,让参照前面的博客《Spring Cloud Alibaba 教程(基于首个毕业版)(二):使用Nacos引入服务发现》
Feign的组成
接口 | 作用 | 默认值 |
---|---|---|
Feign.Builder | Feign的入口 | Feign.Builder |
Client | Feign底层用什么去请求 | 和Ribbon配合时:LoadBalancerFeignClient 不和Ribbon配合时feign.Client.Default |
Contract | 契约,注解支持 | SpringMvcContract |
Encoder | 编码器,用于将对象转换成HTTP请求消息体 | SpringEncoder |
Decoder | 解码器,将相应消息体转换成对象 | ResponseEntityDecoder |
Logger | 日志管理器 | Slf4jLogger |
RequestInterceptor | 用于为每个请求添加通用逻辑 | 无 |
Feign细粒度配置定义--以配置日志级别为例
Feign日志级别
级别 | 打印内容 |
---|---|
NONE(默认值) | 不记录任何日志 |
BASIC | 仅记录请求方法、URL、响应状态代码以及执行时间 |
HEADERS | 记录BASIC级别的基础上,记录请求和响应的header |
FULL | 记录请求和响应的header、body和元数据 |
Feign细粒度配置定义(java代码方式)
1. 新建UserCenterFeignConfiguration类
public class UserCenterFeignConfiguration {
@Bean
public Logger.Level Level(){
// 指定feign 打印所有请求的细节
return Logger.Level.FULL;
}
}
2. 修改 CenterUserFeignClient类
@FeignClient(name = "center-user",configuration = UserCenterFeignConfiguration.class)
public interface CenterUserFeignClient {
@GetMapping("/users/{id}")
UserDTO findById(@PathVariable Integer id);
}
3. yml 文件加上logging日志级别
logging:
level:
com.thyme.content.feignclient.CenterUserFeignClient: debug
Feign细粒度配置定义(配置属性的方式)
1. 在yml 文件添加属性
logging:
level:
com.thyme.content.feignclient.CenterUserFeignClient: debug
feign:
client:
config:
#想要调用的微服务的名称
center-user:
loggerLevel: full
Feign全局配置--以配置日志级别为例
Feign全局配置(java代码方式)
1. 新建GlobalFeignConfiguration
public class GlobalFeignConfiguration {
@Bean
public Logger.Level Level(){
// 指定feign 打印所有请求的细节
return Logger.Level.FULL;
}
}
2. 修改启动类application文件
@MapperScan("com.thyme")
@SpringBootApplication
//全局配置
@EnableFeignClients(defaultConfiguration = UserCenterFeignConfiguration.class)
public class ContentApplication {
public static void main(String[] args) {
SpringApplication.run(ContentApplication.class, args);
}
}
3.修改yml 文件日志级别(可以修改的包的范围更大)
logging:
level:
com.thyme.content.feignclient.CenterUserFeignClient: debug
Feign全局配置(配置属性的方式)
1. 修改在yml文件
logging:
level:
com.thyme.content.feignclient.CenterUserFeignClient: debug
feign:
client:
config:
default:
loggerLevel: full
Feign 配置方式对比
代码方式支持的配置型
配置型 | 作用 |
---|---|
Logger.Level | 指定日志级别 |
Retryer | 指定重试策略 |
ErrorDecoder | 指定错误解码器 |
Request.Options | 超时时间 |
Collection<RequestInterceptor> | 拦截器 |
SetterFactory | 用于设置Hystrix的配置属性 Feign整合Hystrix才会用 |
属性方式支持的配置项
feign:
client:
config:
#想要调用的微服务的名称
<feignName>:
# 连接超时时间
connectionTimeout: 5000
# 读取超时时间
readTimeout: 5000
# 日志级别
loggerLevel: full
# 错误解码器
errorDecoder: com.example.SimpleErrorDecoder
# 重试策略
retryer: com.example.SimpleRetryer
# 拦截器
requestInterceptors:
- com.example.FooRequestInterceptor
# 是否对404 错误码解码
decode404: false
# 编码器
encoder: com.example.SimpleEncoder
# 解码器
decoder: com.example.SimpleDecoder
# 契约
contract: com.example.SimpleContract
Feign代码方式VS 属性方式
配置方式 | 优点 | 缺点 |
---|---|---|
代码配置 | 基于代码,更加灵活 | 如果Feign的配置类加了Configuration注解,需注意父子上下文 线上修改得重新打包、发布 |
属性配置 | 易上手 配置更加直观 线上修改无需重新打包、发布优先级更高 | 极端场景下没有代码配置方式灵活 |
总结:
- 尽量使用属性配置,属性方式实现不了的情况下再考虑用代码配置
- 在同一个微服务内尽量保持单一性,比如统一使用属性配置,不要两种方式混用,增加定位代码的复杂性
Ribbon配置 vs Feign配置
方式 | 粒度 | Ribbon | Feign |
---|---|---|---|
代码方式 | 局部 | @RibbonClient(configuration=XXX.class) X 必须加@Configuration, 且必须放在父上下文无法扫描的包 | @FeignClient(configuration=Y.class) Y的 @Configuration可选, 如果有,必须放在父上下文无法扫描的包 |
全局 | @RibbonClients(defaultConfiguration) | @EnableFeignClients(defaultConfiguration) | |
属性方式 | 局部 | <clientName>.ribbon.NFLoadBalancerClassName ..... | feign.client.config.<clientName>.loggerLevel ... |
全局 | -- | feign.client.config.default.loggerLevel ... |
Feign 多参数请求构造
Feign常见问题总结
RestTemplate VS Feign
角度 | RestTemplate | Feign |
---|---|---|
可读性、可维护性 | 一般 | 极佳 |
开发体验 | 欠佳 | 极佳 |
性能 | 很好 | 中等(RestTemplate的50%左右) |
灵活性 | 极佳 | 中等(内置功能可满足绝大多数需求) |