Spring Cloud(三):Web服務客戶端之Feign

前文介紹了實現客戶端負載均衡的Ribbon,但直接使用Ribbon的API來實現服務間的調用相對較爲繁瑣,服務間的調用可否像本地接口調用同樣便捷、透明,更符合編程習慣呢?Feign就是用來幹這事的。html

Feign

Feign是一個聲明式的Web服務客戶端,讓服務之間的調用變得很是簡單——定義帶@FeignClient註解的接口,本地直接@Autowired 接口,經過調用接口的方法來實現遠程服務的調用。git

 支持的註解包括Feign註解與JAX-RS(Java API for RESTful Web Services)註解。github

 每個Feign的客戶端都包含一系列對應的組件,Spring Cloud經過FeignClientsConfiguration 爲每個命名的Feign客戶端建立一個組件集合,包括feign.Decoder,feign.Encoder,feign.Contract等。web

 

Feign提供的默認bean實現及說明spring

Bean類型 默認實現類 說明
Decoder ResponseEntityDecoder ResponseEntityDecoder封裝了SpringDecoder,解碼器,將服務的響應消息進行解碼
Encoder SpringEncoder 編碼器
Logger Slf4jLogger 日誌框架
Contract SpringMvcContract 支持註解契約,使用SpringMvcContract能夠對Spring MVC註解提供支持
Feign.Builder HystrixFeign.Builder 使用斷路器來裝飾Feign接口
Client LoadBalancerFeignClient 若是是ribbon則 LoadBalancerFeignClient, 若是是spring cloud LoadBalancer 則 FeignBlockingLoadBalancerClient,默認ribbon

 

跟Ribbon相似,能夠經過配置類來自定義Feign客戶端,如編程

@FeignClient(name = "hello-service", configuration = CustomConfiguration.class) public interface StoreClient { //..
} public class CustomConfiguration { @Bean public Contract feignContract() { return new feign.Contract.Default(); } @Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor() { return new BasicAuthRequestInterceptor("user", "password"); } }

 

這樣Feign客戶端就包含了FeignClientsConfiguration 與CustomConfiguration 中定義的組件,而且後者會覆蓋前者(即自定義配置的優先級高於默認配置)。 微信

 

自定義配置類不須要加註解@Configuration,若是加了且被@ComponentScan掃描到,則將成爲全部Feign客戶端的默認配置app

 

一樣Feign客戶端也支持經過配置文件來配置負載均衡

feign: client: config: feignName: connectTimeout: 5000 readTimeout: 5000 loggerLevel: full errorDecoder: com.example.SimpleErrorDecoder retryer: com.example.SimpleRetryer requestInterceptors: - com.example.FooRequestInterceptor - com.example.BarRequestInterceptor decode404: false encoder: com.example.SimpleEncoder decoder: com.example.SimpleDecoder contract: com.example.SimpleContract

 


對於應用於全部Feign客戶端的全局默認配置,也能夠經過兩種方式 框架

  1. 經過@EnableFeignClients 的defaultConfiguration 屬性指定默認配置類

  2. 在配置文件中經過名稱爲default的配置實現

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

     

優先級同Ribbon, 配置文件>自定義配置類>默認的FeignClientsConfiguration


案例演示

本文案例演示基於前面搭建的springcloud-eureka 與 springcloud-eureka-client 兩個示例項目。

  1. 新建springcloud-feign項目,pom.xml中加入依賴

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

     spring-cloud-starter-openfeign 包含了spring-cloud-starter-netflix-ribbon 與 spring-cloud-starter-loadbalancer。

 

  1. 啓動類加上@EnableFeignClients 註解

    @SpringBootApplication @EnableFeignClients public class FeignApplication { public static void main(String[] args) { SpringApplication.run(FeignApplication.class, args); } }

     

  2. 定義Feign client(feign client支持繼承)

    @FeignClient("hello-service") public interface HelloClient extends BaseHelloClient{ @RequestMapping("hello/param") String hello(@SpringQueryMap QueryParam param); }

     

  3. 調用Feign client

    @RestController public class FeignController { @Autowired private HelloClient helloClient; @RequestMapping("feign") public String feignTest(){ return "調用Hello-service返回:" + helloClient.hello(); } @RequestMapping("feign/param") public String feignTestParam(QueryParam param) { return "調用Hello-service返回:" + helloClient.hello(param); } }

     

依次啓動三個項目,調用http://localhost:8083/feign 能正常返回調用hello-service的結果。

 本示例項目還經過@SrpingQueryMap 註解實現了Feign對 pojo用於GET請求參數的支持。若是不加@SrpingQueryMap, 則pojo參數是沒法經過Feign client傳遞的,可去掉註解自行驗證下。


一些知識點

  1. 若是須要定製化產生的查詢參數map,能夠實現並注入一個自定義的 QueryMapEncoder bean

  2. Feign client的日誌可經過feign client接口的全路徑名進行配置,如logging.level.project.user.UserClient: DEBUG,默認爲NONE(即不打印日誌)。全局設置

    @Configuration public class FooConfiguration { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }

    可設置的level值

    • NONE:不記錄日誌 ,默認

    • BASIC:只記錄請求方法,url,以及響應狀態碼與執行時間

    • HEADERS:包括BASIC與請求、響應頭

    • FULL:包括請求與響應的headers,body,metadata

  1. Feign默認使用Ribbon來作負載均衡,可經過配置spring.cloud.loadbalancer.ribbon.enabled=false 來使用spring cloud loadbalancer(目前Ribbon處於維護狀態,近期內不作更新)

  2. 可經過配置feign.okhttp.enabled=true 或 feign.httpclient.enabled=true 來使用OkHttpClient 或ApacheHttpClient, 默認使用的是JDK 原生的URLConnection 發送HTTP請求,沒有鏈接池

  3. 若是須要在RequestInterceptor 中使用ThreadLocal中的變量, 那麼要麼禁用Hystrix,要麼設置hystrix的線程隔離策略爲SEMAPHORE

    feign: hystrix: enabled: false # 或者 hystrix: command: default: execution: isolation: strategy: SEMAPHORE
  4. 使用有Hystrix fallback的Feign時,會在ApplicationContext中存在多個同類型bean, 致使@Autowired 失效。爲了解決這個問題,Spring cloud netflix 將全部feign實例標爲@Primary,若是要關閉該特性, 可將@FeignClient的 primary屬性置爲false。

    @FeignClient(name = "hello", primary = false) public interface HelloClient { // ...
    }

     

本文示例代碼:https://github.com/ronwxy/springcloud-demos

 


 

認真生活,快樂分享
歡迎關注微信公衆號:空山新雨的技術空間

 

 

 

原文出處:https://www.cnblogs.com/spec-dog/p/12217166.html

相關文章
相關標籤/搜索