自定义Feign配置

  1. java代码的方式

    • 写一个配置类
    public class FeignConfig {
        /**
         * 将契约改为feign原生的默认契约。这样就可以使用feign自带的注解了。
         * @return 默认的原生契约
         */
        @Bean
        public Contract feignContract(){
            return new Contract.Default();
        }
    }
    
    • 在注解上添加该类
    @FeignClient(name="user-provider",configuration = FeignConfig.class)
    public interface UserFeignClient {
        /**
         * 使用feign自带的注解@RequestLine
         * @param id
         * @return
         */
        @RequestLine("GET /user/{id}")
        User getById(@Param("id") Integer id);
    }
    
  2. 配置文件中配置

    feign:
      client:
        config:
          user-provider:  # 写了这个就是对某个服务,若用default就是全局设置
            connectTimeout: 5000
            readTimeout: 5000
            loggerLevel: full
            encoder: feign.form.spring.SpringFormEncoder
            requestInterceptors:
              - com.example.feign2.interceptor.RequestHeaderInterceptor
    
  3. 日志

    • Logger.Level的值有以下选择:

      • NONE: 不记录任何日志(默认值)
      • BASIC: 仅记录请求方法、URL、响应状态代码以及执行时间。
      • HEADERS: 记录basic级别的基础上,记录请求和响应的header。
      • FULL: 记录请求和响应的header、body和元数据。
  4. 性能调优

    • feign底层客户端实现默认使用的是URLConnection,这是jdk自带的发送http请求的包,不支持连接池;这样在发送http请求时,每次都要建立连接(三次握手),发送数据,断开连接(四次挥手),比较浪费性能、消耗时间

    • 推荐使用另外两种底层实现(OKHttp,Apache HttpClient其中更推荐Apache HttpClient);

    • 日志级别推荐设置basic和none,性能更好

    • 引入依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
    • 添加配置
    feign:
      client:
        config:
          default: # default全局的配置
            loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
      httpclient:
        enabled: true # 开启feign对HttpClient的支持
        max-connections: 200 # 最大的连接数
        max-connections-per-route: 50 # 每个路径的最大连接数
    
  5. 最佳实践

    • 方式一:继承与实现(不怎么推荐)
      feign的客户端(服务消费者)和服务端(服务提供者)定义一个统一的父接口,这样统一管理,更加系统化
      缺点:高耦合

    • 方式二:抽取(推荐使用)
      以前是客户端(服务消费者)写一套对服务端(服务提供者)的feign接口,这样当服务增多,每个服务都要写一套对该服务端的feign接口,且修改时也要一一修改;
      现在反过来,由服务提供者自己抽取出一个feign的独立模块,其他服务中引入这个模块,即可调用这个服务了,缺点是消费者不能选择某个服务者中某个单一的服务进行消费

    • 解释:userservice为服务提供者,orderservice为服务消费者,那我只需要新增(抽取)一个模块,对userservice所有的对外接口、实体类都写到这个模块(feign接口模块)里面来,那么其他所有的模块要使用userservice模块,向userservice发送请求,只需引入userservice的那个feign接口模块,即可使用,所有的服务消费者都使用userservice提供的这一套feign接口

    • 创建一个module,命名为feign-api,然后引入feign的starter依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
    • 将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中

    • 在order-service中引入feign-api的依赖

    • 修改order-service中的所有与上述三个组件有关的import部分,改成导入feign-api中的包

    • 当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用,有两种解决方案:

    • 指定Feign应该扫描的包:

    @EnableFeignClients(basePackages = "cn.itcast.feign.clients")
    
    • 指定需要加载的Client接口:
    @EnableFeignClients(clients = {UserClient.class})
    
posted @ 2024-05-23 22:07  Hanyta  阅读(91)  评论(0编辑  收藏  举报