天天看點

Spring Cloud入門之服務調用OpenFeignSpring Cloud 之 OpenFeign

Spring Cloud 之 OpenFeign

1、Feign 簡介

  Spring Cloud OpenFeign是一套基于Netflix Feign實作的聲明式、模闆化的服務調用用戶端,Feign可以幫助我們更快捷、優雅地調用HTTP API,它使得編寫Web服務用戶端變得更加簡單。我們隻需要通過建立接口并用注解來配置它既可完成對Web服務接口的綁定。它具備可插拔的注解支援,包括Feign注解、JAX-RS注解。它也支援可插拔的編碼器和解碼器。Spring Cloud Feign還擴充了對Spring MVC注解的支援,同時還整合了Ribbon和Eureka來提供均衡負載的HTTP用戶端實作。

官方文檔:《Declarative REST Client: Feign》。

2、簡單使用

  在前面學習《Eureka注冊中心》和《用戶端負載均衡》中,我們一直使用了RestTemplate進行服務接口的調用,這個時候我們需要知道服務接口的具體資訊,比如:IP位址或服務名、端口号、接口位址等,這種使用近似原始Http方式的調動,為我們編寫代碼帶來了很大的複雜度。而Feign就是封裝了這些細節,為我們提供了更加快捷和優雅的調用HTTP API的方法,我們下面拭目以待:

1、建構基于Feign的消費者用戶端

  注冊中心和服務提供者可以使用前面例子中的應用,這裡隻需要重構消費者引用即可,因為Feign本身就是為了簡化開發者編寫消費服務接口的HTTP封裝。

2、引入Feign依賴

  在原來的消費基礎上,增加Feign相關依賴即可,如下:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
           
3、開啟Feign功能

  開啟Feign功能很簡單,隻需要在啟動類中添加@EnableFeignClients注解接口,這樣就啟動了Feign功能。

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class EurekaConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaConsumerApplication.class, args);
    }

}
           
4、定義Feign接口

  定義Feign接口是實作Feign調用非常重要和基礎的工作,Feign就是根據定義的接口和其中的注解實作了服務接口的調用,同時目前應用隻需要像本地類一樣調用對應的方法即可。

@FeignClient("eureka-provider")
public interface FeignApiClient {

    @GetMapping("/provider")
    String provider();
    
}
           

  在上述代碼中,@FeignClient注解作用目标在接口上,用來表示該接口作為一個FeignClient使用,其中的value,表示FeignClient的名稱(如果使用了服務注冊中心,一般使用服務提供者的名稱),如果項目使用了Ribbon,value屬性會作為微服務的名稱,用于服務發現。而@GetMapping注解,主要用來指定在對應的服務提供者中的HTTP API,即該方法被調用時,實際調用服務提供者的位址。

5、編寫消費者Controller

  這裡隻需要一個定義一個普通的Controller類即可,其中需要把前面定義的Feign接口類FeignApiClient注入到該類中即可,這個時候,我們就可以像使用普通的service類一樣,調用該接口的指定方法了。

@RestController
public class FeignController {

    Logger logger = Logger.getLogger(FeignController.class);

    @Autowired
    private FeignApiClient feignApiClient;

    @RequestMapping("/feignApi")
    public String feignApi(){
        logger.info("執行消費者FeignController的feignApi()方法!");
        return feignApiClient.provider();
    }
}
           
6、啟動、驗證

  啟動應用,正常啟動後,通路http://localhost:8020/feignApi,這個時候,服務提供者的接口就被正常調用了,消費者也傳回了正确的資訊。這個時候,Feign的簡單執行個體我們就完成了,這裡我們隻是簡單了建構了一個基于Feign的消費者,我們下面再嘗試一些其他的用法。

3、 Feign日志級别

3.1、單個服務的日志配置

  啟用Feign日志配置需要兩步:

  第一步,在配置檔案application.properties中增加相關配置:

# 啟用Feign日志級别
logging.level.com.qriver.cloud.consumer.feign.FeignApiClient: DEBUG
           

  其中,logging.level是固定字首,com.qriver.cloud.consumer.feign.FeignApiClient是對應的Feign接口的權限定類名,對應的Value值隻能是DEBUG類型。

  第二步,增加Feign日志的配置類或增加相應配置。

  如果使用配置檔案形式,在配置檔案application.properties中增加下面配置即可,其中feign.client.config是固定格式,eureka-provider是服務提供者的應用名稱,logger-level固定格式,full是選用的日志級别。

feign.client.config.eureka-provider.logger-level: full
           

  如果選擇增加Feign日志的配置類的方式,代碼如下:

@Configuration
public class FeignLoggingConfig {

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}
           

  在上述配置類中,我們使用了FULL級别的日志,無論使用配置檔案還是配置類的方式,這種都是針對每一個微服務的服務提供者進行配置的。

3.2、全局日志配置

  Feign日志進行全局配置時,也是需要兩步:

  第一步,定義需要輸出日志的地方,這個和java web中普通日志方式是一樣的,即配置需要列印日志的包配置。

# 啟用Feign日志級别
logging.level.com.qriver.cloud.consumer.feign.*: DEBUG
           

  第二步,增加Feign全局日志配置,和單個服務配置類似,也有配置類和配置檔案兩種方式。

  如果使用配置檔案方式,隻需要在配置檔案中增加如下配置即可:

feign.client.config.default.logger-level: full
           
和單個服務提供者日志配置相比,這裡把服務名稱改成default即可。

  如果選擇使用配置類,配置類的定義方法和前面為單個服務定義的配置類是一樣的。隻需要把@Configuration注解移除就可以了,這裡不再重複貼出。全局日志配置的引入方式,需要修改啟用Feign的注解@EnableFeignClients,增加defaultConfiguration屬性,并把配置類引入即可,代碼如下:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(defaultConfiguration = FeignLoggingConfig.class)
public class EurekaConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaConsumerApplication.class, args);
    }

}
           
3.3、Feign日志級别

  Feign一共有四種級别的日志,分别是:

  1. NONE: 不記錄任何日志資訊,這是預設值。
  2. BASIC:僅記錄請求的方法,URL及響應狀态和執行時間,類似于Tomcat預設的通路日志。
  3. HEADERS:在BASIC的基礎上,額外記錄了請求和響應的頭資訊
  4. FULL:記錄了所有請求和響應的明細,包括頭資訊、請求體和中繼資料等。

  下面貼出來四種不同級别,列印的日志示例:

FULL級别:

2020-11-08 14:53:07.697  INFO 2504 --- [nio-8020-exec-1] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client eureka-provider initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=eureka-provider,current list of Servers=[localhost:8010],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;	Instance count:1;	Active connections count: 0;	Circuit breaker tripped count: 0;	Active connections per server: 0.0;]
},Server stats: [[Server:localhost:8010;	Zone:defaultZone;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 08:00:00 CST 1970;	First connection made: Thu Jan 01 08:00:00 CST 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
]}ServerList:org.springf[email protected]66e383de
2020-11-08 14:53:07.830 DEBUG 2504 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] <--- HTTP/1.1 200 (490ms)
2020-11-08 14:53:07.831 DEBUG 2504 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] connection: keep-alive
2020-11-08 14:53:07.831 DEBUG 2504 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] content-length: 12
2020-11-08 14:53:07.831 DEBUG 2504 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] content-type: text/plain;charset=UTF-8
2020-11-08 14:53:07.831 DEBUG 2504 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] date: Sun, 08 Nov 2020 06:53:07 GMT
2020-11-08 14:53:07.831 DEBUG 2504 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] keep-alive: timeout=60
2020-11-08 14:53:07.831 DEBUG 2504 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] 
2020-11-08 14:53:07.833 DEBUG 2504 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] Hello World!
2020-11-08 14:53:07.834 DEBUG 2504 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] <--- END HTTP (12-byte body)
2020-11-08 14:53:08.661  INFO 2504 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: eureka-provider.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
           

HEADERS級别:

2020-11-08 14:55:45.091  INFO 10800 --- [nio-8020-exec-1] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client eureka-provider initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=eureka-provider,current list of Servers=[localhost:8010],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;	Instance count:1;	Active connections count: 0;	Circuit breaker tripped count: 0;	Active connections per server: 0.0;]
},Server stats: [[Server:localhost:8010;	Zone:defaultZone;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 08:00:00 CST 1970;	First connection made: Thu Jan 01 08:00:00 CST 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
]}ServerList:org.springf[email protected]7e8dcbf2
2020-11-08 14:55:45.179 DEBUG 10800 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] <--- HTTP/1.1 200 (375ms)
2020-11-08 14:55:45.179 DEBUG 10800 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] connection: keep-alive
2020-11-08 14:55:45.179 DEBUG 10800 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] content-length: 12
2020-11-08 14:55:45.179 DEBUG 10800 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] content-type: text/plain;charset=UTF-8
2020-11-08 14:55:45.179 DEBUG 10800 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] date: Sun, 08 Nov 2020 06:55:45 GMT
2020-11-08 14:55:45.179 DEBUG 10800 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] keep-alive: timeout=60
2020-11-08 14:55:45.180 DEBUG 10800 --- [nio-8020-exec-1] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] <--- END HTTP (12-byte body)
2020-11-08 14:55:46.061  INFO 10800 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: eureka-provider.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
           

BASIC級别:

2020-11-08 14:59:01.149  INFO 94780 --- [nio-8020-exec-2] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client eureka-provider initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=eureka-provider,current list of Servers=[localhost:8010],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;	Instance count:1;	Active connections count: 0;	Circuit breaker tripped count: 0;	Active connections per server: 0.0;]
},Server stats: [[Server:localhost:8010;	Zone:defaultZone;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 08:00:00 CST 1970;	First connection made: Thu Jan 01 08:00:00 CST 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
]}ServerList:org.springf[email protected]23aa7540
2020-11-08 14:59:01.239 DEBUG 94780 --- [nio-8020-exec-2] c.q.cloud.consumer.feign.FeignApiClient  : [FeignApiClient#provider] <--- HTTP/1.1 200 (393ms)
2020-11-08 14:59:02.117  INFO 94780 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: eureka-provider.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
           

NONE級别:

2020-11-08 15:00:40.790  INFO 44616 --- [nio-8020-exec-1] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client eureka-provider initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=eureka-provider,current list of Servers=[localhost:8010],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;	Instance count:1;	Active connections count: 0;	Circuit breaker tripped count: 0;	Active connections per server: 0.0;]
},Server stats: [[Server:localhost:8010;	Zone:defaultZone;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 08:00:00 CST 1970;	First connection made: Thu Jan 01 08:00:00 CST 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
]}ServerList:org.springf[email protected]739c9f13
2020-11-08 15:00:41.759  INFO 44616 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: eureka-provider.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
           

4、壓縮請求和響應資料

  為了提高請求資料和響應資料在網絡中的傳輸效率,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
           

5、基于Ribbon的負載均衡

  Feign實作基于Ribbon的負載均衡非常容易。首先,需要引入Ribbon的依賴檔案,如下所示:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
           

  然後,在定義Feign接口的時候,@FeignClient注解name或value屬性使用服務名稱(不綁定具體執行個體位址即可)即可。

5.1、準備環境

  驗證所需的環境和《用戶端負載均衡》中所需的環境一樣,然後重構消費者就可以了,而且消費者隻需要引入ribbon依賴,Feign就會自動的啟用負載均衡機制。

5.2、驗證

  啟動後,通過多次通路接口,就會發現服務提供者均勻的分别到了兩個服務上,說明負載均衡生效了。這裡隻是簡單的實作了負載均衡,我們後面再詳細分析他們是如何進行工作的。

繼續閱讀