跟我學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/

乾貨分享

全是乾貨

相關文章
相關標籤/搜索