SpringCloud(七)之Feign(详解和实例)

转载请注明出处:https://blog.csdn.net/weixin_41133233/article/details/85070323
本文出自 程熙cjp 的博客

继上一篇讲述完Hystrix的详解和实例之后,本篇小熙将会讲述Feign的详解和实例。

一. Feign的简介

Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编码器和解码器。Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。

二. 配置案例环境

  1. 导入feign的坐标和重试机制的坐标

    	<!--导入feign-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
    
    	<!--导入重试机制的坐标-->
            <dependency>
                <groupId>org.springframework.retry</groupId>
                <artifactId>spring-retry</artifactId>
            </dependency>
    
  2. 开启SpringBoot启动类的支持

    开启feign注解

  3. 配置yml文件

    server:
      port: 8094
    spring:
      application:
    #   注册服务的名称,注意服务器名称不能使用下划线连接,可以使用中划线连接
        name: user-consumer
      cloud:
    # 开启SpringCloud负载均衡中的重试功能,ribbon中整合了(默认是重试到熔断机制的时间),但是zuul整合时需要指定
        loadbalancer:
          retry:
            enabled: true # 开启Spring Cloud的重试功能
    user-service:   # 注意这是提供某一服务系统的服务名称,仅对这一服务起作用,不能随意抒写
      ribbon:
    #    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule  # 修改ribbon中默认的轮询为随机(采用spring系统提供包)
        ConnectTimeout: 250 # Ribbon的连接超时时间
        ReadTimeout: 1000 # Ribbon的数据读取超时时间
        OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
        MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
        MaxAutoRetries: 1 # 对当前实例的重试次数
    eureka:
      client:
    #    注册eureka的地址
        service-url:
          defaultZone: http://127.0.0.1:8090/eureka,http://127.0.0.1:8091/eureka,http://127.0.0.1:8092/eureka
      instance:
    #   当其它服务获取地址时提供ip而不是hostname
        prefer-ip-address: true
    #   指定自己的ip信息,不指定的话会自己寻找
        ip-address: 127.0.0.1
    # 设置hystrix的超时时间为6000ms,因为ribbon默认的重试时间和熔断机制的默认时间都是1000毫秒,所以先触发熔断机制。
    # 为了让重试机制生效所以熔断机制的默认时间一定要比ribbon的重试时间长
    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 6000
    # 开启Feign的熔断功能
    feign:
      hystrix:
        enabled: true
    # 请求和响应进行压缩,GZIP压缩,以减少通信过程中的性能损耗
    #  compression:
    # 开启请求压缩
    #    request:
    #      enabled: true
    ## 设置压缩的数据类型
    ##       mime-types: text/html,application/xml,application/json
    ##      min-request-size: 2048 # 设置触发压缩的大小下限
    ## 开启响应压缩
    #    response:
    #      enabled: true
    logging:
      level:
        com.chengxi: debug
    
  4. 解释

    (1)为什么要导入重试坐标

    虽然整合了ribbon但是feign相当于重新整合了客户端,用到的只是原理所以要导入重试机制的坐标用于实例化

    (2)为什么要开启熔断机制

    扫描二维码关注公众号,回复: 4667776 查看本文章

    因为虽然整合了hystrix但是默认是关闭的

    依赖如图:

    依赖坐标图

  5. 如图:抒写消费端关于feign的代码
    feign

    (1) FeignConfig

    package com.chengxi.config;
    
    import feign.Logger;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     *  这里是配置feign的日记级别类,因为feign注解修改的客户端被代理的时候,
     *  都会创建一个新的Feign.Logger实例,所以在配置文件中简单配置没有用,
     *  需要额外指定,并把配置文件放到feign接口的客户端中
     *
     *   详细级别依次递增
     * - NONE:不记录任何日志信息,这是默认值。
     * - BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
     * - HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
     * - FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
     *
     *
     * @author chengxi
     * @date 2018/12/4 23:31
     */
    @Configuration
    public class FeignConfig {
    
        /**
         * feign日志记录的设置
         * @return
         */
        @Bean
        Logger.Level feignLoggerLevel(){
            return Logger.Level.FULL;
        }
    
    }
    
    

    (2)UserFeignClient

    package com.chengxi.feign;
    
    import com.chengxi.config.FeignConfig;
    import com.chengxi.pojo.TUser;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    /**
     *  dec:在feign注解中配置要访问的服务类(value的值),fallback是feign访问超时,熔断机制的回滚函数,一般是继承此接口的类(注意不同于feign帮我们实现接口中的实现类)
     *  feign的熔断机制是关闭的,需要在配置文件中配置。只要在fallback后面写上回滚函数类即可,对应实现方法会自动调用
     *  configuration:是对于当前feign代理的客户端的配置文件
     *
     *  如果参数是对象,请求就不会成功,即使指定了Get方法,feign依然会以Post方式进行发送请求。
     * 	解决方案:@RequestParam("id") Long id,@RequestParam("name") Long name
     *
     *
     * @author chengxi
     * @date 2018/12/4 22:20
     */
    @FeignClient(value = "user-service",fallback = UserFeignClientFallback.class,configuration = FeignConfig.class)
    public interface UserFeignClient {
    
        /**
         * feign根据GetMapping中的路径加上对应服务的地址找到对应的方法,如类上注解的服务名+GetMapping中的路径
         * 注意这里 @PathVariable 的注解中的参数不能省略,如现在的id,他是将输入的的参数通过注解参数传给Mapping中的路径参数。
         *      可以看成从路径中获取参数,但是注解参数不能省略且三个参数值还必须一致
         * @param id
         * @return
         */
        @GetMapping(value = "/userService/{id}")
        public TUser selectUserById(@PathVariable("id") Integer id);
    
    
    }
    
    

    (3)UserFeignClientFallback

    package com.chengxi.feign;
    
    import com.chengxi.pojo.TUser;
    import org.springframework.stereotype.Component;
    
    /**
     *  feign的失败回滚函数类
     * 
     * 
     * @author chengxi
     * @date 2018/12/4 23:00
     */
    @Component
    public class UserFeignClientFallback implements UserFeignClient {
    
        /**
         *  在配置文件中开启feign的熔断机制,然后继承feign的访问服务类的接口实现其方法作为访问服务类方法失败的回滚方法,当然也需要在feign接口中定义
         * @param id
         * @return
         */
        @Override
        public TUser selectUserById(Integer id) {
            TUser user = new TUser();
            user.setId(id);
            user.setUsername("用户查询异常");
            return user;
        }
    }
    

    (4)UserController中添加测试feign的方法

    @Autowired
        private UserFeignClient userFeignClient;
    
        /**
         * 采用feign对http的rest请求进行封装,自己不再用拼接,实现了松耦合。feign是对Eureka和ribbon的整合,提供负载均衡
         *  对应接口的@FeignClient注解中的服务名称加上调用方法的GetMapping的value构成请求路径,再由feign实现接口返回结果给我们
         * @param ids
         * @return
         */
        @GetMapping(value = "/selectUsersByIdAndFeign")
        public List<TUser> selectUsersByIdAndFeign(@RequestParam ArrayList<Integer> ids){
            ArrayList<TUser> tUsers = new ArrayList<>();
    
            ids.forEach(id -> {
                tUsers.add(userFeignClient.selectUserById(id));
            });
    
            return tUsers;
        }
    

至此,关于feign配置的环境就完成了。

三. 测试运行

  1. 直接运行,由于feign的读取超时的时间是1000毫秒,如图(失败的即调用feign对应方法的失败回调函数)
    熔断未生效
    熔断未生效

    以上的多次询问是因为Ribbon相关配置的生效,所以访问时间超过1000毫秒的都没有查询成功(即请求和响应的总时间必须在1000毫秒以内完成)。
    这里我们需要配置下Ribbon的读取超时的时间,改为6000毫秒即可

  2. 修改完之后,结果如图:
    修改之后的结果

经过小熙的测试(由于小熙在服务提供者哪里,设置的睡眠时长较长),配置时长不仅需要配置hystrix的还需要配置ribbon的(在feign中请求访问时间比Ribbon的读取超时的时间长也是失败的),但是建议ribbon的比hystrix的短一点。

还是建议修改配置,因为项目中可能也有请求正常但是时间过长的问题存在,这里演示下抛错以及解决方法。

嗯,至此小熙对于Feign的简介和实例就讲述完了。下篇小熙将会讲解关于zuul的详解和实例

猜你喜欢

转载自blog.csdn.net/weixin_41133233/article/details/85141410