跟我学Spring Cloud(Finchley版)-10-Feign深刻

上一节( 跟我学Spring Cloud(Finchley版)-09-Feign )讲了Feign的入门姿式并深刻对比了RestTemplate,本节来深刻探讨Feign的高级特性。总的来讲,Feign是一个相对简单的组件,但细节仍是比较多的,一不当心就可能入坑,注意点我会以WARINING的形式标记出来,便于读者查阅。java

Feign配置自定义【细粒度配置】

方式1、代码配置方式

Spring Cloud Netflix provides the following beans by default for feign (BeanType beanName: ClassName):git

  • Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecoder)
  • Encoder feignEncoder: SpringEncoder
  • Logger feignLogger: Slf4jLogger
  • Contract feignContract: SpringMvcContract
  • Feign.Builder feignBuilder: HystrixFeign.Builder
  • Client feignClient: if Ribbon is enabled it is a LoadBalancerFeignClient, otherwise the default feign client is used.

The OkHttpClient and ApacheHttpClient feign clients can be used by setting feign.okhttp.enabled orfeign.httpclient.enabled to true, respectively, and having them on the classpath.github

Spring Cloud Netflix does not provide the following beans by default for feign, but still looks up beans of these types from the application context to create the feign client:spring

  • Logger.Level
  • Retryer
  • ErrorDecoder
  • Request.Options
  • Collection<RequestInterceptor>
  • SetterFactory

代码示例:自定义日志级别

默认Feign是不打印任何日志的,下面咱们来开启Feign的日志,Feign有四种日志级别:json

  • NONE【性能最佳,适用于生产】:不记录任何日志(默认值)。
  • BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间。
  • HEADERS:记录BASIC级别的基础上,记录请求和响应的header。
  • FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数据。

插科打诨 & 恶意揣测app

跟我学Spring Cloud(Finchley版)-09-Feign说过,Feign的性能中等,可能官方对本身的性能也是知道的,索性所有关闭日志了,哈哈ide

  • 将前文的Feign Client修改成以下:性能

    @FeignClient(name = "microservice-provider-user", configuration = UserFeignConfig.class)
    public interface UserFeignClient {
      @GetMapping("/users/{id}")
      User findById(@PathVariable("id") Long id);
    }
    
    /**
     * 该Feign Client的配置类,注意:
     * 1. 该类能够独立出去;
     * 2. 该类上也可添加@Configuration声明是一个配置类;
     * 配置类上也可添加@Configuration注解,声明这是一个配置类;
     * 但此时千万别将该放置在主应用程序上下文@ComponentScan所扫描的包中,
     * 不然,该配置将会被全部Feign Client共享,没法实现细粒度配置!
     * 我的建议:像我同样,不加@Configuration注解
     *
     * @author zhouli
     */
    class UserFeignConfig {
      @Bean
      public Logger.Level logger() {
        return Logger.Level.FULL;
      }
    }

    如代码所示,使用注解@FeignClientconfiguration 属性,指定一个类,便可实现Feign配置自定义。测试

    TIPSui

    • 本例简单起见,直接弄了个外部类做为配置类UserFeignConfig,读者也可将该类独立出去做为一个public class

    WARNING

    • 配置类上也可添加@Configuraiton 注解,声明这是一个配置类;但此时千万别将该放置在主应用程序上下文@ComponentScan 所扫描的包中,不然,该配置将会被全部Feign Client共享(至关于变成了通用配置,其实本质仍是Spring父子上下文扫描包重叠致使的问题),没法实现细粒度配置!
    • 我的建议:像我同样,不加@Configuration注解,免得进坑。

    联想记忆

    还记得Ribbon如何使用Java代码自定义配置吗?Ribbon使用Java代码自定义配置时也必须防止配置类在@ComponentScan 上下文内,详见: 跟我学Spring Cloud(Finchley版)-08-Ribbon深刻

  • application.yml 中添加如下内容,将该Feign接口的日志级别设置为DEBUG:

    logging:
      level:
        com.itmuch.cloud.study.user.feign.UserFeignClient: debug
  • 此时,当该Feign Client的方法被调用时,将会打印相似以下的日志:

    2019-01-10 22:14:10.611 DEBUG 26321 --- [nio-8010-exec-2] c.i.c.study.user.feign.UserFeignClient   : [UserFeignClient#findById] ---> GET http://microservice-provider-user/users/1 HTTP/1.1
    2019-01-10 22:14:10.611 DEBUG 26321 --- [nio-8010-exec-2] c.i.c.study.user.feign.UserFeignClient   : [UserFeignClient#findById] ---> END HTTP (0-byte body)
    2019-01-10 22:14:10.623 DEBUG 26321 --- [nio-8010-exec-2] c.i.c.study.user.feign.UserFeignClient   : [UserFeignClient#findById] <--- HTTP/1.1 200 (11ms)
    2019-01-10 22:14:10.623 DEBUG 26321 --- [nio-8010-exec-2] c.i.c.study.user.feign.UserFeignClient   : [UserFeignClient#findById] content-type: application/json;charset=UTF-8
    2019-01-10 22:14:10.623 DEBUG 26321 --- [nio-8010-exec-2] c.i.c.study.user.feign.UserFeignClient   : [UserFeignClient#findById] date: Thu, 10 Jan 2019 14:14:10 GMT
    2019-01-10 22:14:10.623 DEBUG 26321 --- [nio-8010-exec-2] c.i.c.study.user.feign.UserFeignClient   : [UserFeignClient#findById] transfer-encoding: chunked
    2019-01-10 22:14:10.623 DEBUG 26321 --- [nio-8010-exec-2] c.i.c.study.user.feign.UserFeignClient   : [UserFeignClient#findById] 
    2019-01-10 22:14:10.624 DEBUG 26321 --- [nio-8010-exec-2] c.i.c.study.user.feign.UserFeignClient   : [UserFeignClient#findById] {"id":1,"username":"account1","name":"张三","age":20,"balance":100.00}
    2019-01-10 22:14:10.624 DEBUG 26321 --- [nio-8010-exec-2] c.i.c.study.user.feign.UserFeignClient   : [UserFeignClient#findById] <--- END HTTP (72-byte body)

配套代码

GitHub:https://github.com/eacdy/spring-cloud-study/tree/master/2018-Finchley/microservice-consumer-movie-feign-config-java

Gitee:https://gitee.com/itmuch/spring-cloud-study/tree/master/2018-Finchley/microservice-consumer-movie-feign-config-java

方法2、属性配置方式【Edgware开始提供】

从Spring Cloud Edgware开始,Feign支持使用属性自定义Feign。对于一个指定名称的Feign Client(例如该Feign Client的名称为feignName ),Feign支持以下配置项:

feign:
  client:
    config:
      feignName:
        connectTimeout: 5000  # 至关于Request.Options
        readTimeout: 5000     # 至关于Request.Options
        # 配置Feign的日志级别,至关于代码配置方式中的Logger
        loggerLevel: full
        # Feign的错误解X码X器,至关于代码配置方式中的ErrorDecoder
        errorDecoder: com.example.SimpleErrorDecoder
        # 配置重试,至关于代码配置方式中的Retryer
        retryer: com.example.SimpleRetryer
        # 配置拦截器,至关于代码配置方式中的RequestInterceptor
        requestInterceptors:
          - com.example.FooRequestInterceptor
          - com.example.BarRequestInterceptor
        decode404: false

TIPS

我的并不建议配置retryer,Spring Cloud Camden以及以后的版本中,Spring Cloud关闭了Feign的重试,而是使用Ribbon的重试。若是本身再定义Feign的重试后,那么可能会形成重试特性的混乱。笔者已在https://github.com/spring-cloud/spring-cloud-netflix/issues/2330 提出该问题。

代码示例:自定义日志级别

要想用属性配置方式来达到上面Java代码方式的效果,只需在application.yml 中添加以下内容便可:

feign:
  client:
    config:
      microservice-provider-user:
        loggerLevel: full
logging:
  level:
    com.itmuch.cloud.study.user.feign.UserFeignClient: debug

配套代码

GitHub:https://github.com/eacdy/spring-cloud-study/tree/master/2018-Finchley/microservice-consumer-movie-feign-config-properties

Gitee:https://gitee.com/itmuch/spring-cloud-study/tree/master/2018-Finchley/microservice-consumer-movie-feign-config-properties

Feign配置自定义【通用配置】

上面讨论了如何配置特定名称的Feign Client,那么若是想为全部的Feign Client都进行配置,该怎么办呢?咱们知道,@EnableFeignClients 注解上有个defaultConfiguration 属性,咱们能够将默认配置写成一个类,而后用defaultConfiguration 来引用,例如:

@EnableFeignClients(defaultConfiguration = DefaultRibbonConfig.class)

若是想使用配置属性的方式,只需使用相似以下的写法便可。

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: basic

配置优先级

若是你不当心又使用了Java代码配置Feign,同时又使用了配置属性配置Feign,那么使用配置属性的优先级更高。配置属性配置的方式将会覆盖Java代码配置。若是你想修改代码配置方式的优先级,可以使用以下属性:feign.client.default-to-properties=false

压缩

一些场景下,咱们可能须要对请求或响应进行压缩,此时可以使用如下属性启用Feign的压缩功能。

feign.compression.request.enabled=true
feign.compression.response.enabled=true

对于请求的压缩,Feign还提供了更为详细的设置,例如:

feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048

其中,feign.compression.request.mime-types 用于支持的媒体类型列表,默认是text/xml、application/xml以及application/json。

feign.compression.request.min-request-size 用于设置请求的最小阈值,默认是2048。

继承

比较重要,业界对继承特性见解很是不同,喜欢的特别喜欢,讨厌的特别讨厌(例如我)。将以番外形式体现,并对比二者优缺点,以及最佳实践,明天或后天更新,敬请期待。

其余特性

Feign其余特性我已经写了不少了,知识体系已经完备了。懒得再在这个系列里凑字数,这不是个人风格,直接贴地址吧:

本文首发

http://www.itmuch.com/spring-cloud/finchley-10/

干货分享

全是干货

相关文章
相关标签/搜索