天天看點

Spring Cloud 七:Feign聲明式服務調用介紹與使用

一,了解Feign

1,什麼是Feign

Netflix Feign

Feign是Netflix開發的聲明式、模闆化的HTTP用戶端, Feign可以幫助我們更快捷、優雅地調用HTTP API。

Feign實際上是對普通HTTP用戶端的一層封裝,其目的是降低內建成本、提升可靠性。Feign支援三種HTTP用戶端,包括JDK自帶的HttpURLConnection、Apache HttpClient和Square OkHttp,預設使用Apache HttpClient。

Spring Cloud Feign

Spring Cloud Feign是基于Netflix Feign實作,對Netflix Feign進行了增強,使Feign支援了Spring MVC注解,整合了Spring Cloud Ribbon和Spring Cloud Hystrix 提供負載均衡和斷路器。

2,Feign和Open Feign

其實Feign和Open Feign他倆是屬于同一個東西,Feign

僅僅隻是改名成為了

Open Feign而已,然後Open Feign項目在其基礎上繼續發展至今。

spring-cloud-starter-feign 從

1.2.0.RELEASE

開始 已放棄Netflix Feign而全面使用更新的Open Feign版本,

spring-cloud-starter-openfeign更是和Netflix Feign已經沒有關系了。

二,Feign的使用

1,服務消費方使用

1.1,起一個eureka服務:

Spring Cloud 七:Feign聲明式服務調用介紹與使用

1.2,向eureka-server中注冊一個服務提供者eureka-provider

application.yaml

spring:
  application:
    name: eureka-provider
eureka:
  client:
    service-url:
      defaultZone: http://euk-server1:7001/eureka/
  instance:
    hostname: euk-client1
           

HelloController.java

@RestController
public class HelloController {

    @Value("${server.port}")
    private String port;

    @GetMapping("/testFeign")
    public String testFeign() {
        System.out.println("port:" + port);
        return "服務提供者,端口為:" + port;
    }
}
           
Spring Cloud 七:Feign聲明式服務調用介紹與使用

1.3,使用Feign向eureka-server注冊服務消費者

導入Open Feign

<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
           

配置appliation.yml 注冊到Eureka Server。

eureka:
  instance:
    hostname: localhost
  client:
    service-url:
      defaultZone: http://euk-server1:7001/eureka/
spring:
  application:
    name: eureka-consumer
server:
  port: 7008
           

使用@FeignClient為本應用聲明一個簡單的能調用的用戶端,value是需要調用的服務名。

@FeignClient(value = "eureka-provider")
public interface FeignInterface {
    @RequestMapping("/testFeign")
    public String testFeign();
}
           

接收外部請求,通過Feign遠端調用服務

@RestController
public class FeignController {
    @Autowired
    private FeignInterface feignInterface;

    @RequestMapping("/testFeign")
    public String testFeign() {
        return feignInterface.testFeign();
    }
}
           

在啟動類上添加 @EnableFeignClients 啟用 Feign

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class EurekaConsumer1Application {

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

啟動eureka-consumer然後通路http://localhost:7008/testFeign 傳回結果:

Spring Cloud 七:Feign聲明式服務調用介紹與使用

2,Fegin的繼承特性使用

Spring Cloud Feign提供了繼承特性,所謂的繼承特性就是将一些公共操作提取到一個父接口中,進而繼承父接口中的操作,減少代碼的重複開發,節約開發成本。

  1. 編寫通用服務接口A,接口方法上寫@RequestMapping(),此接口用于 feign。
  2. 服務提供者 實作上面接口A。
  3. 服務消費者的feign client接口 繼承A。

優點:

可以将接口的定義從 Controller 中剝離,同時配合 Maven 私有倉庫就可以輕易地實作接口定義的共享,不用再複制粘貼接口進行綁定,而是實作在建構期的接口綁定,進而有效減少服務用戶端的綁定配置。

缺點:

由于接口在建構期間就建立起了依賴,那麼接口變動就會對項目建構造成影響,可能服務提供方修改了一個接口定義,那麼會直接導緻用戶端工程的建構失敗。

2.1:首先我們建立一個通用model,eureka-feign-api

由于我們要用到spring mvc,是以pom.xml中要依賴spring web子產品

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
           

建立通用接口HelloInterface.java,用于eureka-provider實作,eureka-consumer繼承:

@RequestMapping("/feign")
@RestController
public interface HelloInterface {
    @GetMapping("/hello")
    String hello();
}
           

2.2:eureka-provider依賴eureka-feign-api并實作其通用接口HelloInterface

eureka-provider的pom添加依賴eureka-feign-api

<dependency>
     <groupId>com.bobo</groupId>
     <artifactId>eureka-feign-api</artifactId>
     <version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
           

eureka-provider的controller實作通用接口HelloInterface

@RestController
public class FeignCommonProviderController implements HelloInterface {

    @Value("${server.port}")
    private int port;

    @Override
    public String hello() {
        return "服務提供者,我的端口為:" + port;
    }
}
           

eureka-provider啟動類

@SpringBootApplication
@EnableEurekaClient
public class EurekaProviderApplication {

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

}
           

3.3:eureka-consumer依賴eureka-feign-api并繼承其通用接口HelloInterface

eureka-consumer的pom依賴添加eureka-feign-api

<dependency>
     <groupId>com.bobo</groupId>
     <artifactId>eureka-feign-api</artifactId>
     <version>0.0.1-SNAPSHOT</version>
</dependency>
<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>
           

eureka-consumer繼承通用接口HelloInterface

@FeignClient("eureka-provider")
public interface FeignCommonInterface extends HelloInterface {
}
           

eureka-consumer通過FeignCommonInterface來實作Feign的調用

@RestController
public class FeignCommonController {
    @Autowired
    private FeignCommonInterface commonInterface;

    @GetMapping("/hello")
    public String hello(){
        return commonInterface.hello();
    }
}
           

eureka-consumer啟動類

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class EurekaConsumerApplication {

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

}
           

然後啟動eureka-server,eureka-provider,eureka-consumer,通過服務調用eureka-consumer

http://euk-client2:7008/hello 輸出:

Spring Cloud 七:Feign聲明式服務調用介紹與使用

三,Feign配置

feign的預設配置類是:org.springframework.cloud.openfeign.FeignClientsConfiguration。預設定義了feign使用的編碼器,解碼器等。

Feign允許自定義配置,自定義配置有如下兩種方式:

  1. 一種是Java 代碼配置,需要在@FeignClient(name = “eureka-consumer”,configuration = FeignAuthConfiguration.class)來引用配置。
  2. 第二種是直接配置檔案配置,在application.yml或者application.properties中配置。

1,Java代碼配置

public class FeignAutoConfiguration {
    @Bean
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
        return new BasicAuthRequestInterceptor("root", "root");
    }
}
           
@FeignClient(value = "eureka-provider",configuration = FeignAutoConfiguration.class)
public interface FeignCommonInterface extends HelloInterface {
}
           

如果在配置類上添加了@Configuration注解,并且該類在@ComponentScan所掃描的包中,那麼該類中的配置資訊就會被所有的@FeignClient共享。

最佳實踐是:不指定@Configuration注解,而是手動:@FeignClient(name = “eureka-provider”,configuration = FeignAuthConfiguration.class)

2,配置檔案配置

自定義攔截器:

/**
 * @author bobo
 * @date 2020-12-08
 * 自定義攔截器
 */

public class MyBasicAuthRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header("Authorization", "Basic cm9vdDpyb290");
    }
}
           

application.yaml

spring:
  application:
    name: eureka-consumer
eureka:
  client:
    service-url:
      defaultZone: http://euk-server1:7001/eureka/
  instance:
    hostname: euk-client2
server:
  port: 7008

feign:
  client:
    config:
      eureka-peovider:
        request-interceptors:
           com.bobo.eurekaconsumer.MyBasicAuthRequestInterceptor
           

3,擴充

自定服務名稱配置:

feign:
     client: 
       config:  
         service-valuation: 
           connect-timeout: 5000
           read-timeout: 5000
           logger-level: full
           

通用配置:

feign:
     client: 
       config:  
         default: 
           connect-timeout: 5000
           read-timeout: 5000
           logger-level: full
           

4,Feign壓縮

Spring Cloud Feign 支援請求和響應進行GZIP壓縮來提高通信效率,但是會增加CPU壓力,建議把最小壓縮的文檔大小适度調大一點,進行gzip壓縮。

# 開啟GZIP壓縮配置:
      
      #請求GZIP壓縮
      feign.compression.request.enable=true                 
      #響應GIZP壓縮
      feign.compression.response.enable=true              
      #壓縮支援的mime type
      feign.compression.request.mime-types=text/xml,application/xml.application/json                  
      feign.compression.request.min-request-size=1024         
      #壓縮資料大小的最小值
           

5,Feign日志

Feign 為每一個FeignClient都提供了feign.logger執行個體,可在配置中或者java代碼中開啟日志。

feign:
  client: 
    config:  
	  # 服務名稱
      eureka-provider:  
        logger-level: basic
           

上面logger-level有4種日志類型:

  1. none:不記錄任何日志,預設值。
  2. basic:僅記錄請求方法,url,響應狀态碼,執行時間。
  3. headers:在basic基礎上,記錄header資訊。
  4. full:記錄請求和響應的header,body,中繼資料。

上面的logger-level隻對下面的 debug級别日志做出響應:

logging:
  level:
    com.bobo.eureka-consumer.ServiceForecast: debug
           

四,寫在最後

上述例子代碼已上傳碼雲:https://gitee.com/songbozhao/spring-cloud-feign-test

繼續閱讀