【SpringCloud】3.OpenFeign——服務註冊與負載均衡

陆陆无为而治者發表於2024-12-05

基本介紹

之前學了LoadBalance,已經能實現負載均衡了,為什麼還需要學習OpoenFeign。簡單的說:LoadBalancer能做的事情,OpenFeign都能做,LoadBalance不能做的事情,OpenFeign也能做。

基本介紹

OpenFeign,主要用於負載均衡,是一個宣告式的Web服務客戶端,從而使WEB服務的呼叫變得很簡單。同時OpenFeign還有一些高階特性,例如超發控制、重試機制、預設HttpClient修改,請求響應壓縮、OpenFeign日誌列印。OpenFeign已經是當前微服務呼叫最常用的技術

能做什麼

我們在使用LoadBalancer+RestTemplate實現了微服務的負載均衡呼叫,但是在實際開發中,一個介面往往會被多處呼叫,這就需要多次定義重複的程式碼,而OpenFeign簡化了這個過程 。而且也可整合阿里巴巴的Sentinel來提供熔斷、降級功能。透過OpenFeign只需要定義服務繫結介面且以宣告式的方法,就能夠優雅而且簡單的實現服務呼叫。

OpenFeign通用步驟

前面我們已經學習了loadBlancer的引用,https://www.cnblogs.com/luyj00436/p/18580829。OpenFeign使用的原理如下:
image

接下來使用OpenFeign,為了區別LoadBalancer引用,這裡新建了一個訂單子工程。
image

引入OpenFeign和LoadBalancer的依賴

訂單子工程引入OpenFeign和LoadBalancer的依賴。

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

啟動類上加上@EnableFeignClients註解

訂單子工程(服務引用端),在啟動類上新增註解``啟動OPenFeignClient功能。

@SpringBootApplication
@EnableDiscoveryClient  // 向consul註冊中心時提供服務
@EnableFeignClients(basePackages = "com.atguigu.cloud") //如果FeignClient不在SpringBootApplication的掃描範圍內可以在@EnableFeignClients中指定掃描範圍
public class MainFeign80 {
    public static void main(String[] args) {
        SpringApplication.run(MainFeign80.class, args);
    }
}

在專案通用方法中api包,並儲存api介面

在通用方法中,也引入OpenFeign的依賴。

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

新建支付模組介面
image

支付模組中,新增@FeignClient註解,註解的值就是被呼叫的微服務方法。編寫介面中方法,方法上的註解就是別呼叫方法的請求型別和地址。返回值需要和被呼叫介面返回值一致。

@FeignClient(value = "cloud-payment-service")
public interface PayFeignApi {
    /**
     * 新增訂單
     * @return
     */
    @PostMapping("/pay/add")
    public ResultData<String> addPay();

    /**
     * 根據Id刪除訂單
     * @param id
     * @return
     */
    @DeleteMapping("/pay/del/{id}")
    public ResultData<Integer> deletePay(@PathVariable("id") Integer id);

    /**
     * 更新訂單資訊
     * @param payDTO
     * @return
     */
    @PutMapping("/pay/update")
    public  ResultData<String> updatePay(@RequestBody PayDTO payDTO);

    /**
     * 根據Id獲取訂單資訊
     * @param id
     * @return
     */
    @GetMapping("/pay/get/{id}")
    public ResultData<Pay> getById(@RequestParam("id") Integer id);

    /**
     * 獲取所有的訂單資訊
     * @return
     */
    @GetMapping("/pay/gets")
    public ResultData<List> getPayList();

    /**
     * 獲取埠號
     * @param request
     * @return
     */
    @GetMapping("/pay/get/port")
    public ResultData<String> getPort();
}

呼叫微服務模組(支付模組,cloud-openfeign-order80)調傭feign介面方法

開啟支付模組,新建呼叫方feign方法。

// 注入feign物件
@Resource
private PayFeignApi payFeignApi;

image
測試後,發現能夠成功呼叫微服務。

OpenFeign的高階特性

前面已經完成了業務模組的基礎使用。接下來,學習一些OpenFeign的高階特性,以應對微服務呼叫時的一些復操作。

OpenFeign超時控制

OpenFeign客戶端的預設等待時間60S,超過這個時間就會報錯

如果業務程式碼比較複雜或者網路原因,有可能出現超時。我們可以設定預設的超時時間。分為兩種設定方式全域性配置指定設定。指定設定優先順序高於全域性設定。

全域性設定

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
          #指定超時時間最大:3S
            read-timeout: 3000
            #指定連線時間最大:3S
            connect-timeout: 3000

指定設定

spring:
  cloud:
    openfeign:
      client:
        config:
        #這裡將default換成微服務的名稱
          cloud-payment-service:
          #指定超時時間最大:3S
            read-timeout: 3000
            #指定連線時間最大:3S
            connect-timeout: 3000

注:可以修改被呼叫的支付模組等待時間,驗證超時控制時間。

try {
    TimeUnit.SECONDS.sleep(62);	// 設定等待62s
}catch (InterruptedException e){
    e.printStackTrace();
}

此時,超時報錯如下:
image

OpenFeign重試機制

預設情況下,超時連線會返回一個錯。如果我們希望重新嘗試連線呢?

重試機制預設時關閉的,我們只需要編寫一個配置類,配置Retryer物件。

新增OpenFeign的配置類,設定重試機制

@Configuration
public class FeignConfig {
    @Bean
    public Retryer retryer(){
        // Retryer.Default( long period, long maxPeriod, int maxAttempts)
        // period : 多長時間後開啟重試機制,這裡設定100ms
        // maxPeriod : 重試間隔,這裡設定1s一次
        // maxAttempts : 最大請求次數,這裡設定3次
        return new Retryer.Default(100,1,3);
    }
}

執行測試重試:
image
image

前面配置時,設定等待時間3s。3次重試,開始時間和結束時間的時間差為9s。沒有3次重試的過程,需要後續開啟日誌列印才可以看到。

OpenFeign預設HttpClient修改

為什麼要修改HttpClient呢?

OpenFeign中的HttpClient預設採用的是JDK自帶的HttpUrlConection傳送HTTP請求。由於JDK的HttpUrlConection沒有連線池,效能和效率上相對較低。

例如當我們遇到連線超時的錯誤時,也能看到是HttpURLConnection丟擲的異常~這也能進一步證明預設採用的是HttpURLConnection
image

因此實際開發中,切換成Apache HttpClient 5是很有必要的。

步驟如下:1. 引入依賴;2. 開啟配置說明

引入依賴

<!-- apche HttpClient的引用-->
<dependency>
	<groupId>org.apache.httpcomponents.client5</groupId>
	<artifactId>httpclient5</artifactId>
	<version>5.2.1</version>
</dependency>
<dependency>
	<groupId>io.github.openfeign</groupId>
	<artifactId>feign-hc5</artifactId>
	<version>13.3</version>
</dependency>

開啟配置(yml檔案為例)

feign:
  httpclient:
    hc5:
      enabled: true # 這是2.x的寫法
# --------------- 以下是SpringBoot 3.0 寫法 ---------------
spring:
  cloud:
    openfeign:
      httpclient:
        hc5:
          enabled: true

此時,測試超時報錯,已經全部是HttpClient 5

1733366949341

OpenFeign請求/響應壓縮

OpenFeign支援對請求和響應進行GZIP壓縮,以減少通訊過程中的效能損耗

spring:
  cloud:
    openfeign:
      compression:
        request:
        #開啟請求壓縮
          enabled: true
          #達到多大才觸發壓縮
          min-request-size: 2048
          #觸發壓縮的型別
          mime-types: types=text/xml,application/xml,application/json
        response:
          #開啟響應壓縮
          enabled: true

OpenFeign日誌列印功能

OpenFeign需要輸出日誌需要符合兩個條件:

  1. FeignClient所在的包日誌級別為debug
  2. Feign的日誌級別在NONE以上

Feign的日誌級別:
NONE:不記錄任何日誌資訊,這是預設值。
BASIC:僅記錄請求的方法,URL以及響應狀態碼和執行時間
HEADERS:在BASIC的基礎上,額外記錄了請求和響應的頭資訊
FULL:記錄所有請求和響應的明細,包括頭資訊、請求體、後設資料。

步驟:定義一個類定義Feign的日誌級別

public class DefaultFeignConfig {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.FULL;//日誌級別
    }
}

配置檔案中設定feign所在包的列印級別

logging:
  level:
  #下面是feign介面的包
    com:
      atguigu:
        cloud:
          apis:
            PayFeignApi: debug 

日誌開啟後,可以看到N次請求。
image

所謂念念不忘,必有迴響。但……如果呼叫的伺服器一直不能給我們回應,一直請求也不是個事兒,否則成了dos攻擊了。這時候需要接受服務降級了。後續學到阿里巴巴的Sentinel,可以結合起來使用。

OpenFeign和Sentinel能夠實現服務降級

之前學了LoadBalance

相關文章