• Spring Cloud 之OpenFeign


    Spring Cloud 之OpenFeign

    一:简介

    ​ Feign是一个声明式(对比RestTemplate编程式)的服务客户端,即通过@FeignClient注解即可声明一个接口(interface)。还支持多种插拔式的配置如encoders/decoders(加解码),clients(不同的链接框架)...... 。Spring Cloud 集成了 Eureka、Spring Cloud Breaker 以及 Spring Cloud LoadBalancer,便可实现 Feign 负载平衡的 http 客户端。

    二: 使用方式一(单独使用)

    2.1:引入依赖
    <dependency>
        <groupId>io.github.openfeigngroupId>
        <artifactId>feign-coreartifactId>
        <version>??feign.version??version>
    dependency>
    
    2.2:定义接口
    interface GitHub {
      @RequestLine("GET /repos/{owner}/{repo}/contributors")
      List contributors(@Param("owner") String owner, @Param("repo") String repo);
    }
    
    public static class Contributor {
      String login;
      int contributions;
    }
    
    2.3 : 构造Feign的 http 客户端 示例
    public class MyApp {
      public static void main(String... args) {
        GitHub github = Feign.builder()
                             .decoder(new GsonDecoder()) 
                             .target(GitHub.class, "https://api.github.com");
    
        List contributors = github.contributors("OpenFeign", "feign");
        for (Contributor contributor : contributors) {
          System.out.println(contributor.login + " (" + contributor.contributions + ")");
        }
      }
    }
    

    示例解释:

    2.3.1 :接口地址‘ https://api.github.com/repos/OpenFeign/feign/contributors’是一个获取github上OpenFeign项目的贡献者名单信息。
    2.3.2 :Feign.builder(构建者模式(23种设计模式之一)).decoder指定解析器(返回的是json数组).target指定指定目标对象(接口和url)
    2.3.3 :自定义其他参数

    .encoder(加析器),errorDecoder(异常解析器).client(指定使用的客户端)....再次不一一介绍。

    小结: 通过简介以及一个简单的示例,我们已经明了了Feign用法和架构,下面就看springcloud如何集成Feign

    三:springcloud集成Feign

    3.1:启动类加@EnableFeignClients注解开启声明式Feign,
    @SpringBootApplication
    @EnableFeignClients
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    
    3.2: 通过interface定义接口地址(复用2.2:定义接口)
    interface GitHub {
      @RequestLine("GET /repos/{owner}/{repo}/contributors")
      List contributors(@Param("owner") String owner, @Param("repo") String repo);
    }
    
    3.3:通过@FeignClient注解(相当于 Feign.builder()) 定义远程服务地址和其他组件
       @FeignClient(url = "服务名地址(https://api.github.com)" ,value = "服务名(springboot项目的项目名与url二选一)")
    interface GitHub {
      @RequestLine("GET /repos/{owner}/{repo}/contributors")
      List contributors(@Param("owner") String owner, @Param("repo") String repo);
    }
    

    四:集成feign后的常见需求

    4.1 Feign调用失败后的错误分析

    fallbackFactory :错误后的返回信息 推荐使用相比fallback可辨知错误原因)

    fallback:错误后的返回信息

    #配置文件中需开启错误分析
    feign:
      hystrix:  # 老版本
        enabled: true
      circuitbreaker: #新版本
        enabled: true
     # If true, an OpenFeign client will be wrapped with a Hystrix circuit breaker,Hystrix的默认隔离级别事线程,故feign的拦截器与调用不在同一个线程内
    
    4.1.2 fallbackFactory 示例
    @Component
    public class FallbackFactoryGitHub implements FallbackFactory {
        private static final Logger logger = LoggerFactory.getLogger(GitHub.class);
    
        @Override
        public GitHub create(Throwable throwable) {
            return new GitHub() {
                @Override
                public String contributors( String owner, String  repo)  {
                    logger.error("contributors", throwable);
                    return throwable.getMessage();
                }
    			.....
            };
        }
    }
    

    4.2 服务间通过Feign调用,会丢失请求头的信息()

    4.2.1 步骤一:定义RequestInterceptor传的请求头信息:
    @Bean
    public RequestInterceptor headerInterceptor() {
            return template -> {
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                //(feign.hystrix.enabled: true)  attributes 为 null
                if (null != attributes) {
                    attributes.getRequest();
                    HttpServletRequest request = attributes.getRequest();
                    Enumeration headerNames = request.getHeaderNames();
                    if (headerNames != null) {
                        while (headerNames.hasMoreElements()) {
                            String name = headerNames.nextElement();
                            String values = request.getHeader(name);
                            // 跳过 content-length
                            if (name.equals("content-length")){
                                continue;
                            }
                            template.header(name, values);
                        }
                    }
                }
            };
        }
    
    4.2.2 指定配置
    @FeignClient(.... , configuration = XXX.class)
    

    五:参考资料

    5.1 https://docs.spring.io/spring-cloud-openfeign/docs/3.1.8/reference/html

    5.2 https://github.com/OpenFeign/feign

    最后期待负载均衡客户段是如何实现的

  • 相关阅读:
    计算机毕业论文选题推荐|软件工程|系列八
    好心情精神心理科:抑郁症,真的会让你变丑!
    .NET周报 【2月第3期 2023-02-18】
    从Excel的一个工作表中获取第一行(标题行)的单元格内容-代码解释
    Redis基本全局命令(含key过期策略)
    CSS 小球随着椭圆移动
    Mysql分组查询每组最新的一条数据
    Kotlin开发Android之基础问题记录
    基于单片机音乐弹奏播放DS1302万年历显示及源程序
    RK3588 实现温控风扇之通过extcon子系统上报状态(三)
  • 原文地址:https://www.cnblogs.com/jinliang374003909/p/17557847.html