栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Feign

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Feign

Feign
  • 1.Feign是什么
  • 2.Feign能干什么?
  • 3.Feign的使用
    • 3.1添加依赖
    • 3.2配置Feign
    • 3.3feign的日志
    • 3.4Feign使用OKhttp发送request
  • 4.Feign原理简述
  • 5.feign源码分析
    • 5.1EnableFeignClients

1.Feign是什么

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组合使用以支持负载均衡

2.Feign能干什么?

Feign旨在简化微服务消费方(调用者,客户端)代码的开发,前面在使用Ribbon+RestTemplate进行服务调用时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方式,但是在实际开发中,由于服务提供者提供的接口非常多,一个接口也可能会被多处调用,Feign在Ribbon+RestTemplate的基础上做了进一步封装,在Feign封装之后,我们只需创建一个接口并使用注解的方式来配置,即可完成对服务提供方的接口绑定,简化了使用Ribbon + RestTemplate的调用,自动封装服务调用客户端,减少代码开发量

3.Feign的使用 3.1添加依赖

    org.springframework.cloud
    spring-cloud-starter-openfeign

3.2配置Feign

从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负载均衡地发起调用。
5.feign源码分析

通过上面的使用过程,@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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/463153.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号