天天看點

[04] 入門Spring Cloud_OpenFeign 子產品間調用一、OpenFeign 子產品間調用二、目前項目結構介紹三、項目中添加 Feign四、請求逾時處理五、日志列印

一、OpenFeign 子產品間調用

現在的項目中已經使用 RestTemplate 實作子產品間的調用,為什麼還要使用 OpenFeign

因為 RestTemplate 是基于類調用,每次調用都需要 new 出 RestTemplate 類,耦合性很強。

1. OpenFeign 介紹

介紹 OpenFeign 之前先來介紹 Feign:

  • feign 是一個聲明式的Web服務用戶端,讓編寫Web服務用戶端變得非常容易,隻需要建立一個接口并在接口上添加注釋即可
  • Spring Cloud 對 Feign 進行了封裝,使其支援了 SpringMVC 标準注解和 HttpMessageConverters 。 Feign 可以與 Eureka 和 Ribbon 組合使用以支援負載均衡。

使用的目的為了用接口的方式讓子產品之間的調用更加靈活,而不是 new 出一個個的類

Feign 內建了 Ribbon ,與 Ribbon 不同的是,通過 Feign 隻需要定義服務綁定接口且以聲明式的方法,優雅而簡單的實作了服務調用。

OpenFeign 是 Spring Cloud 在 Feign 的基礎上繼續進行封裝,支援了 SpringMVC 的注釋,如@RequesMapping等等。

OpenFeign 的 @FeignClient 可以解析 SpringMVC 的 @RequesMapping 注釋下的接口,并通過動态代理的方式産生實作類,實作類中做負載均衡并調用其他服務。

2. 使用方式

服務提供方(生産者)和服務調用方(消費者)在注冊中心注冊後,服務調用方由原來的 Ribbon + RestTemplate 的方式改為使用 OpenFeign 方式調用,使用方式為:

微服務調用接口 + @FeignClient

[04] 入門Spring Cloud_OpenFeign 子產品間調用一、OpenFeign 子產品間調用二、目前項目結構介紹三、項目中添加 Feign四、請求逾時處理五、日志列印

二、目前項目結構介紹

目前項目中包含四個子產品:

[04] 入門Spring Cloud_OpenFeign 子產品間調用一、OpenFeign 子產品間調用二、目前項目結構介紹三、項目中添加 Feign四、請求逾時處理五、日志列印
  • 公有API:cloud-api-commons
  • 服務提供者: cloud-provider-payment8001/8002 (端口号8001 和 8002 )
  • 服務消費者: cloud-consumer-order80 (端口号80 )
  • 注冊中心 Eureka: cloud-eureka-server7001(端口号7001 )

前文連結: https://blog.csdn.net/weixin_42547014/article/details/120334570

項目源碼:https://gitee.com/zhangchouchou/spring-cloud-demo

三、項目中添加 Feign

1. 建立子產品

建立一個子產品,命名為

cloud-consumer-feign-order80

,添加方式依舊為 Maven

[04] 入門Spring Cloud_OpenFeign 子產品間調用一、OpenFeign 子產品間調用二、目前項目結構介紹三、項目中添加 Feign四、請求逾時處理五、日志列印

2. POM 引入依賴

注:OpenFeign 也是自帶 Ribbon

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>SpringCloudDemo</artifactId>
        <groupId>org.zjh.springclouddemo</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-feign-order80</artifactId>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>

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

        <!--Eureka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.zjh.springclouddemo</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

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

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

        <!--熱部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--小辣椒-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

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

    </dependencies>

</project>
           

3. 添加 YML

server:
  port: 80

spring:
  application:
    name: cloud-consumer-feign-order80

eureka:
  client:
#    是否注冊到eureka
    register-with-eureka: true
#    是否發現相關服務
    fetch-registry: true
#    指定路徑
    service-url:
      defaultZone: http://localhost:7001/eureka
           

4. 建立啟動類

在啟動類上添加 @EnableFeignClients 注解,該注解隻在服務調用方添加即可。

@SpringBootApplication
// Eureka用戶端
@EnableEurekaClient
//服務調用方開啟Feign
@EnableFeignClients
public class FeignConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(FeignConsumerApplication.class,args);
    }
}
           

5. 添加調用接口

添加接口

PaymentFeignService

目錄結構

[04] 入門Spring Cloud_OpenFeign 子產品間調用一、OpenFeign 子產品間調用二、目前項目結構介紹三、項目中添加 Feign四、請求逾時處理五、日志列印
//作為元件被發現
@Component
//指定遠端調用的微服務的名稱
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {
    @GetMapping("/user/get/{id}")
    public CommonResult<User> getByID(@PathVariable("id")Integer id);
}
           

6. 實作 Controller

@RestController
@Slf4j
public class FeignController {

    @Autowired
    private PaymentFeignService paymentFeignService;  //調用遠端的微服務接口

    @GetMapping("/consumer/user/get/{id}")
    public CommonResult<User> getByID(@PathVariable("id")Integer id){
        return paymentFeignService.getByID(id);
    }
}
           

至此便實作了子產品間接口的遠端調用。

7. 驗證

啟動注冊中心 -> 啟動8001端口子產品 -> 啟動建立的子產品

重新整理注冊中心看建立的服務是否注冊上

[04] 入門Spring Cloud_OpenFeign 子產品間調用一、OpenFeign 子產品間調用二、目前項目結構介紹三、項目中添加 Feign四、請求逾時處理五、日志列印

注冊成功後,通路新啟動的80端口進行資料擷取

[04] 入門Spring Cloud_OpenFeign 子產品間調用一、OpenFeign 子產品間調用二、目前項目結構介紹三、項目中添加 Feign四、請求逾時處理五、日志列印

資料成功擷取,說明配置成功。

四、請求逾時處理

子產品之間的調用很有可能出現請求逾時的情況,給 8001 端口的生産者添加一個新的請求,該請求不做任何查詢,在方法中等待幾秒,如下所示:

@GetMapping("/user/timeout")
    public String feignTimeout(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //傳回端口号
        return port;
    }
           

再在剛剛添加的 Feign 方式的消費者的接口中添加方法

[04] 入門Spring Cloud_OpenFeign 子產品間調用一、OpenFeign 子產品間調用二、目前項目結構介紹三、項目中添加 Feign四、請求逾時處理五、日志列印

最後在Controller中添加請求

@GetMapping("/consumer/user/timeout")
    public String feignTimeout(){
        return paymentFeignService.feignTimeout();
    }
           

重新啟動服務并通路路徑,因為 OpenFeign 預設等待1秒,是以會出現請求逾時的錯誤

[04] 入門Spring Cloud_OpenFeign 子產品間調用一、OpenFeign 子產品間調用二、目前項目結構介紹三、項目中添加 Feign四、請求逾時處理五、日志列印

處理方式很簡單,設定逾時時間。

在 YML 中開啟 OpenFeign 用戶端逾時控制。

ribbon:
  ReadTimeout: 5000   #讀取的逾時時間
  ConnectTimeout: 5000  #連結的逾時時間
  MaxAutoRetries: 1  #同一台執行個體最大重試次數,不包括首次調用
  MaxAutoRetriesNextServer: 1  #重試負載均衡其他的執行個體最大重試次數,不包括首次調用
  OkToRetryOnAllOperations: false  #是否所有操作都重試
           

當然,這種方法治标不治本,真正的解決方式是使用斷路器(Hystrix),會在後文講解。

五、日志列印

留意一下控制台可以發現一些列印出來的請求資訊, Feign 支援列印接口調用情況,友善進行接口監控。

[04] 入門Spring Cloud_OpenFeign 子產品間調用一、OpenFeign 子產品間調用二、目前項目結構介紹三、項目中添加 Feign四、請求逾時處理五、日志列印

日志級别:

  • NONE:預設的,不顯示任何日志
  • BASIC:僅記錄請求方法、URL、響應狀态碼及執行時間。
  • HEADERS: 除了BASIC中定義的資訊外,還有請求和響應頭資訊
  • FULL: 除了HEADERS中定義的資訊外,還有請求及響應的正文及中繼資料

配置日志 Bean

@SpringBootConfiguration
public class FeignConfig {

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

YML 中開啟日志的 Feign 用戶端

logging:
  level:
    org.zjh.springcloud.service.PaymentFeignService: debug
           

重新開機後再次查詢資訊,可以看到列印的日志資訊

2021-09-17 17:06:53.825  INFO 808 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: CLOUD-PAYMENT-SERVICE.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2021-09-17 17:06:55.223 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] <--- HTTP/1.1 200 (2906ms)
2021-09-17 17:06:55.223 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] connection: keep-alive
2021-09-17 17:06:55.223 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] content-type: application/json
2021-09-17 17:06:55.223 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] date: Fri, 17 Sep 2021 09:06:55 GMT
2021-09-17 17:06:55.224 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] keep-alive: timeout=60
2021-09-17 17:06:55.224 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] transfer-encoding: chunked
2021-09-17 17:06:55.224 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] 
2021-09-17 17:06:55.225 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] {"code":200,"message":"查詢成功","data":{"id":6,"name":"吳","phone":"19804563454","sex":"女"}}
2021-09-17 17:06:55.225 DEBUG 808 --- [p-nio-80-exec-1] o.z.s.service.PaymentFeignService        : [PaymentFeignService#getByID] <--- END HTTP (100-byte body)
           

繼續閱讀