一、前言

在前面的文章:

  1. SpringCloud之Feign实现声明式客户端负载均衡详细案例
  2. SpringCloud之OpenFeign实现服务间请求头数据传递(OpenFeign拦截器RequestInterceptor的使用)

我们聊了OpenFeign的概述、为什么会使用Feign代替Ribbon、Feign和OpenFeign的区别、详细的OpenFeign实现声明式客户端负载均衡案例、OpenFeign中拦截器RequestInterceptor的使用;

本文我们继续讨论OpenFeign有哪些常用配置?

二、常用配置

1、Feign基础参数配置

配置项作用
Logger.Level指定日志级别
Retryer执行重试策略
ErrorDecoder指定错误解码器
Request.Options超时时间
Collection<RequestInterceptor>拦截器

常见可配置的参数:

  • 超时配置、日志级别、编解码器、拦截器、契约、重试策略
    在这里插入图片描述

1)针对全部服务

feign:
  hystrix:
    # Feign启用断路器,默认为FALSE
    enabled: true
  client:
    config:
      # 针对所有的服务
      default:
        # Feign的连接建立超时时间,默认为10秒
        connectTimeout: 5000
        # Feign的请求处理超时时间,默认为60秒
        readTimeout: 5000
        # 日志级别
        loggerLevel: full
        # 拦截器配置(和@Bean的方式二选一)
        requestInterceptors:
          - com.saint.feign.config.MyFeignRequestInterceptor
        # 错误解码器
        errorDecoder: com.example.SimpleErrorDecoder
        # 重试策略
        retryer: com.example.SimpleRetryer
        # 是否对404错误码解码
        # 处理逻辑详见feign.SynchronousMethodHandler#executeAndDecode
        decode404: false
        # 编码器
        encoder: com.example.SimpleEncoder
        # 解码器
        decoder: com.example.SimpleDecoder
        # 契约
        contract: com.example.SimpleContract

2)针对某个服务

feign:
  hystrix:
    # Feign启用断路器,默认为FALSE
    enabled: true
  client:
    config:
      # 针对某个服务(服务名:SERVICE-A)
      SERVICE-A:
        # Feign的连接建立超时时间,默认为10秒
        connectTimeout: 5000
        # Feign的请求处理超时时间,默认为60秒
        readTimeout: 5000
        # 日志级别
        loggerLevel: full
        # 拦截器配置(和@Bean的方式二选一)
        requestInterceptors:
          - com.saint.feign.config.MyFeignRequestInterceptor
        # 错误解码器
        errorDecoder: com.example.SimpleErrorDecoder
        # 重试策略
        retryer: com.example.SimpleRetryer
        # 是否对404错误码解码
        # 处理逻辑详见feign.SynchronousMethodHandler#executeAndDecode
        decode404: false
        # 编码器
        encoder: com.example.SimpleEncoder
        # 解码器
        decoder: com.example.SimpleDecoder
        # 契约
        contract: com.example.SimpleContract

优先使用针对单个服务的配置

2、Feign数据压缩配置

用户在网络请求过程中,如果传输数据量过大,会造成体验差的问题;因此,我们需要将传输数据做压缩以提升体验。SpringCloud OpenFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。

需要在Consumer端做如下配置:

feign:
  # Feign请求响应压缩配置
  compression:
    request:
      # 开启Feign请求压缩,默认不开启
      enabled: true
      # 配置支持压缩的MIME TYPE,默认为:text/xml,application/xml,application/json
      mime-types: text/xml,application/xml,application/json
      # 触发请求数据压缩的最小Size,默认2048KB
      min-request-size: 2048
    response:
      # 开启Feign响应压缩,默认不开启
      enabled: true
      # 使用GZip解码器,默认不使用
      useGzipDecoder: false

注意从GZIP的自动装配类(FeignContentGzipEncodingAutoConfiguration、FeignAcceptGzipEncodingAutoConfiguration)来看,如果使用的是okhttp,gzip是不生效的;

在这里插入图片描述
在这里插入图片描述

3、日志配置

仅建议大家在测试环境开日志(辅助debug、调试),生产环境一般采用日志采集系统(ELK 或 Kafka那一套)。

1)Feign日志的级别

logger level:none,basic,headers,full
在这里插入图片描述

2)日志配置–局部

日志配置有多种方式:JavaBean方式,属性方式

1> JavaBean方式(自动扫描)

这种方式会导致所有的FeignClient都使用相同的日志级别(不推荐使用)。

(1)Logger.Level实例注册
在启动类可以扫描到的包路径下注入一个Logger.Level实例;

package com.saint.feign.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Saint
 */
@Configuration
public class MyConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

(2)日志输出级别配置
给指定包 / 类配置日志输出级别:

  • 日志输出级别:TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
  • 我们的FeignClient所在的包为:com.siant.feign.client
logging:
  level:
    # root日志以WARN级别输出
    root: WARN
    # com.saint.feign.client包下的日志以DEBUG级别输出
    com.saint.feign.client: DEBUG

效果:

在这里插入图片描述
下面不再重复说明日志输出级别配置,只针对Feign日志配置。

2> JavaBean方式(FeignClient手动指定)

将配置类放在SpringBoot扫描不到的包路径下;

注意:不要给MyConfiguration添加@Configuration注解,否者会出现Spring父子上下文的问题,导致所有的feign都使用该配置类。

package com.saint.configuration;

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Saint
 */
public class MyConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

在FeignClient中指定configuration。

@FeignClient(value = "SERVICE-A",configuration = MyConfiguration.class)
public interface ServiceAClient extends ServiceA {
}
3> 属性方式

通用配置格式:

feign:
  client:
    config:
      <feignName>:
        loggerLevel: full
  • 其中<feignName>为要调用的微服务名称;

以本文的要调用的SERVICE-A服务为例,属性配置方式如下:

feign:
  client:
    config:
      # 针对某个服务
      SERVICE-A:
        # 日志级别
        loggerLevel: full

3)日志配置–全局

Feign日志的全局配置有两种方式:代码方式、属性方式。

1> 代码方式

在启动类中的负责启动FeignClient的注解@EnableFeignClients中添加defaultConfiguration属性,指定一个Feign配置类。

@EnableFeignClients(defaultConfiguration = MyConfiguration.class)
2> 属性方式

日志配置--局部属性方式中的微服务的名称改为default即可;

feign:
  client:
    config:
      # 想要调用的微服务名称
      default:
        loggerLevel: full

三、配置方式对比 / 优先级

1、代码和属性配置方式对比

1> 代码配置:

  • 基于代码、更加灵活;
  • 但是线上修改得重新打包、发布,并且还有小坑(父子上下文问题)

2> 属性配置:

  • 配置更加直观、优先级更高(相对代码配置)
  • 线上修改无需重新打包、发布;但是极端场景下没有代码配置方式灵活。

2、配置优先级

局部优于全局,属性优于代码:

  • 全局代码 < 全局属性 < 细粒度代码 < 细粒度属性

3、细粒度配置的最佳实践:

  1. 尽量使用属性配置,属性方式实现不了的情况下再考虑代码配置。
  2. 同一个微服务内尽量保持单一性,使用同样的配置方式,避免两种方式混用,增加定位代码的复杂性。
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐