目录
问题背景
使用RestTemplate 存在的痛点有哪些?
首先看下RestTemplate 调用http 接口的方式:
eg: restTemplate.getForObject("http://alibaba-nacos/config/get",String.class,"1")
从以上调用方式可以看出其存在如下痛点:
1. 代码的可读性比较差
2. 对于负载的url 难维护
3. 编程的体验差
什么是Feign?
Feign 是Netflix 开源的声明式http 调用客户端。旨在简化http调用
如何使用Feign?
加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
加注解
在 spring boot 启动类添加 @EnableFeignClients(basePackages = "com.springcloud.alibaba.consumer") basePackages 指Feign 接口所在包位置
编码
/**
* @Author zj
* @Date 2021/1/13 11:31
*/
@FeignClient(value = "alibaba-nacos",configuration = FeignConfiguration.class)
public interface AlibabaNacosClient {
@GetMapping("/config/get")
String getConfig();
@PostMapping("/config/getParam")
User getParam(@RequestBody User user);
}
调用
在服务内注入自定义的Feign 接口后,及可以向调用其他Service服务一样进行调用Feign接口
Feign 由哪些组件组成?
接口 | 作用 | 默认值 |
---|---|---|
Feign.Builder | Feign的入口 | Feign.Builder |
Client | Feign底层用什么去请求 | 和Ribbon配合时:LoadBalancerFeignClient不和Ribbon配合时:Fgien.Client.Default |
Contract | 契约,注解支持 | SpringMVCContract |
Encoder | 解码器,用于将独享转换成HTTP请求消息体 | SpringEncoder |
Decoder | 编码器,将相应消息体转成对象 | ResponseEntityDecoder |
Logger | 日志管理器 | Slf4jLogger |
RequestInterceptor | 用于为每个请求添加通用逻辑(拦截器,例子:比如想给每个请求都带上heared) | 无 |
Feign 支持哪些配置项?
配置项 | 作用 |
---|---|
Logger.Level | 指定日志级别 |
Retryer | 指定重试策略 |
ErrorDecoder | 指定错误解码器 |
Request.Options | 超时时间 |
Collection | 拦截器 |
SetterFactory | 用于设置Hystrix的配置属性,Fgien整合Hystrix才会用 |
Feign 工作流程是什么?
Feign 如何设置日志级别?
Feign 有哪些日志级别?
NONE(默认) | 不记录任何日志 |
BASIC(产线环境) | 仅记录请求方法,URL,响应状态代码以及执行时间(适合生产环境) |
HEADERS | 记录BASIC级别的基础上,记录请求和响应的header |
FULL(开发环境) | 记录请求和弦ineader,body和元数据 |
Feign 如何设置日志级别?
feign 设置日志级别有两种方式,一种是基于编码的方式进行设置,一种是基于配置属性的方式进行设置;
编码方式
首先编写Feign 的日志配置规则
/**
* @Author zj
* @Date 2021/1/13 15:07
* 这个类不需要添加@Configuration 注解了,加了需要将该配置移至Spring boot启动类扫描包外,否则也会出现父子上下文重复的问题
*/
public class FeignConfiguration {
@Bean
public Logger.Level level(){
// 让feign 打印所有请求细节日志
return Logger.Level.FULL;
}
}
在Feign 接口类进行引用日志配置@FeignClient(value = "alibaba-nacos",configuration = FeignConfiguration.class)
在配置文件设置日志打印级别(com.springcloud.alibaba.consumer.feignclient是feign 接口所在的包地址)
logging:
level:
com.springcloud.alibaba.consumer.feignclient: debug
配置属性
feign:
client:
config:
# nacos 注册的服务名。将服务名称改成default 则是全局配置
alibaba-nacos:
loggerLevel: full
对比
两种配置方式有优劣是和上节Ribbon 使用编码方式,配置属性配置是一样的。在日常使用过程中,优先级往往是 颗粒度配置属性配置>颗粒度编码配置>全局配置属性配置>全局编码配置
Feign 如何脱离nacos 使用?
其实feign 支持的FeignClient注解有一个属性url .该属性是指定调用接口的http url .当脱离nacos 使用时,可以通过设置该属性,达到调用
/**
* 表示到feign 接口调用时,url 指定的是feign调用的url。通过url 可以指定feign跳转 的url地址
* @Author zj
* @Date 2021/4/26 20:31
*
*/
@FeignClient(name = "baidu",url = "https://www.baidu.com")
public interface ConfigFeignClient {
@RequestMapping("")
public String configGet();
}
Feign 和Ribbon 对比
粒度 | Ribbon | Feign |
---|---|---|
代码局部 | @RibbonClient(configuration=RibbonConfig.class),RibbonConfig类必须加@Configuration,且必须放在父上下文无法扫到的包下 | @FeignClient(configuration=FeignConfig.class),FeignConfig类的@Configuration可以不加(可选),如果有,必须放在父上下文无法扫到的包下 |
代码全局 | @RibbonClients(defaultConfigurtion=RibbonConfig.class) | @EnableFeignClients(defaultConfiguration = FeignConfig.class)… |
配置属性局部 | .ribbon.NFLoadBalancerClassName… | feign.client.config…loggerLevel … |
配置属性全局 | 无 | feign.client.config.default.loggerLevel |
Feign 如何优化?
Feign 默认使用的是HttpUrlConnection ,每次请求创建一个连接,访问量大时,对性能十分的不友善。Feign 默认支持okHttp ,httpClient 等http连接池连接方式;因此我们考虑优化Feign 时,可以通过http 连接池的方式来管理http 连接。下面举例feign 结合httpClient 连接池来优化feign 性能。
加依赖
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>11.0</version>
</dependency>
写配置
feign:
httpclient:
# 开启feign 使用httpclient 做请求
enabled: true
# 最大连接数
max-connections: 200
# 单个路径连接数
max-connections-per-route: 50
Feign 其他问题总结
Feign 在使用过程中其他问题总结可以参考大目老师的http://www.imooc.com/article/289005