- 1.Feign是什么
- 2.Feign能干什么?
- 3.Feign的使用
- 3.1添加依赖
- 3.2配置Feign
- 3.3feign的日志
- 3.4Feign使用OKhttp发送request
- 4.Feign原理简述
- 5.feign源码分析
- 5.1EnableFeignClients
Feign 是 Netflix 公司开发的一个声明式的 REST 调用客户端
(调用远程的restful风格的http接口 的一个组件)
调用组件其实很多,比如:
1、Httpclient(apache)
2、Httpurlconnection (jdk)
3、restTemplate(spring)
4、OkHttp(android)
5、Feign (Netflix) --> 实现非常优雅
Spring Cloud Feign 对 Ribbon 负载均衡进行了简化,在其基础上进行了进一步的封装,在配置上大大简化了开发工作,它是一种声明式的调用方式,它的使用方法是定义一个接口,然后在接口上添加注解,使其支持了Spring MVC标准注解和HttpMessageConverters,Feign可以与Eureka和Ribbon组合使用以支持负载均衡
Feign旨在简化微服务消费方(调用者,客户端)代码的开发,前面在使用Ribbon+RestTemplate进行服务调用时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方式,但是在实际开发中,由于服务提供者提供的接口非常多,一个接口也可能会被多处调用,Feign在Ribbon+RestTemplate的基础上做了进一步封装,在Feign封装之后,我们只需创建一个接口并使用注解的方式来配置,即可完成对服务提供方的接口绑定,简化了使用Ribbon + RestTemplate的调用,自动封装服务调用客户端,减少代码开发量
3.Feign的使用 3.1添加依赖3.2配置Feignorg.springframework.cloud spring-cloud-starter-openfeign
从SpringCloudEdgware开始,Feign支持使用属性自定义Feign。对于一个指定名称的FeignClient(例如该FeignClient的名称为feignName),Feign支持如下配置项
feign:
compression: #支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。通过下面的参数即可开启请求与响应的压缩功能
request:
enabled: true #开启请求压缩
mime-types: text/xml,application/xml,application/json #开启支持压缩的MIME TYPE
min-request-size: 2048 #配置压缩数据大小的下限
response:
enabled: true #开启相应压缩
client:
config:
default:
connectTimeout: 5000 #连接超时时间
readTimeout: 5000 #读超时时间
loggerLevel: full #日志级别
errorDecoder: StashErrorDecoder #Feign的错误解码器,这里我们自定义一个
retryer: CustomRetryer #自定义一个配置重试的方式
requestInterceptors: FeignRequestInterceptor #自定义请求拦截器
decode404: false #配置熔断不处理404
logging:
level:
com.example.nacosCofigClient.service.BuyerService: debug
feign的错误解码器
@Configuration
public class StashErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
if (response.status() >= 400 && response.status() <= 499) {
//这里是给出的自定义异常(先用null啦)
return null;
}
if (response.status() >= 500 && response.status() <= 599) {
//这里是给出的自定义异常(先用null啦)
return null;
}
//这里是其他状态码处理方法(先用null啦)
return null;
}
}
feign的请求拦截器
public class FeignRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Enumeration headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
requestTemplate.header(name, values);
}
}
}
}
请求拦截器要注册成bean
@Configuration
public class FeignInterceptorConfig {
@Bean
public RequestInterceptor requestInterceptor(){
return new FeignRequestInterceptor();
}
}
feign的重试器
@Component
public class CustomRetryer implements Retryer {
//最大重试次数
private int retryMaxAttempt;
//每次重试的间隔时间
private long retryInterval;
private int attempt = 1;
public CustomRetryer(){
}
public CustomRetryer(int retryMaxAttempt, Long retryInterval) {
this.retryMaxAttempt = retryMaxAttempt;
this.retryInterval = retryInterval;
}
@Override
public void continueOrPropagate(RetryableException e) {
System.out.println("Feign retry attempt {} due to {} " + attempt + e.getMessage());
if (attempt++ == retryMaxAttempt) {
throw e;
}
try {
Thread.sleep(retryInterval);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
}
@Override
public Retryer clone() {
return new CustomRetryer(6, 2000L);
}
}
3.3feign的日志
在开发或者运行阶段往往希望看到Feign请求过程的日志记录,默认情况下Feign的日志是没有开启的。要想用属性配置方式来达到日志效果,只需配置一下即可
第一种
@Configuration
public class DefaultFeignConfiguration {
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.BASIC;
}
}
第二种
logging.level.xx : debug : Feign日志只会对日志级别为debug的做出响应
logging:
level:
com.example.nacosCofigClient.service.BuyerService: debug
3.4Feign使用OKhttp发送request
Feign底层默认是使用jdk中的HttpURLConnection发送HTTP请求,feign也提供了OKhttp来发送请求,具体配置如下:
feign:
okhttp:
enabled: true
hystrix:
enabled: true
4.Feign原理简述
- 启动时,程序会进行包扫描,扫描所有包下所有@FeignClient注解的类,并将这些类注入到spring的IOC容器中。当定义的Feign中的接口被调用时,通过JDK的动态代理来生成RequestTemplate。
- RequestTemplate中包含请求的所有信息,如请求参数,请求URL等。
- RequestTemplate声场Request,然后将Request交给client处理,这个client默认是JDK的HTTPUrlConnection,也可以是OKhttp、Apache的HTTPClient等。
- 最后client封装成LoadBaLanceClient,结合ribbon负载均衡地发起调用。
通过上面的使用过程,@EnableFeignClients和@FeignClient两个注解就实现了Feign的功能,那我们从@EnableFeignClients注解开始分析Feign的源码
5.1EnableFeignClients@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@documented
@import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
String[] value() default {};
String[] basePackages() default {};
Class>[] basePackageClasses() default {};
Class>[] defaultConfiguration() default {};
Class>[] clients() default {};
}
剩下的看不懂啦
https://baijiahao.baidu.com/s?id=1698639270980356594&wfr=spider&for=pc



