5. Spring Cloud OpenFeign 宣告式 WebService 客戶端的超詳細使用

Rainbow-Sea發表於2024-11-21

5. Spring Cloud OpenFeign 宣告式 WebService 客戶端的超詳細使用

@

目錄
  • 5. Spring Cloud OpenFeign 宣告式 WebService 客戶端的超詳細使用
  • 前言
  • 1. OpenFeign 介紹
    • 1.1 Feign 和 OpenFeign 區別
  • 2. OpenFeign 應用例項
    • 2.2 注意事項和細節
  • 3. OpenFeign 內建的“日誌配置” 操作
    • 3.1 OpenFeign 配置日誌-應用例項
  • 4. OpenFeign 超時時間設定操作
  • 5. 補充:spring-boot-starter-actuator 是 spring boot 程式的監控系統,可以實現健康檢查
  • 6. 總結:
  • 7. 最後:

前言

  • 對應上一篇學習內容:🌟🌟🌟4. Spring Cloud Ribbon 實現“負載均衡”的詳細配置說明_ribbon升級到了loadbalancer-CSDN部落格
  • 對應下一篇學習內容:🌟🌟🌟

1. OpenFeign 介紹

OpenFeign 是什麼 ?

  1. OpenFeign 是個宣告式 WebService 客戶端,使用 OpenFeign 讓編寫 Web Service客戶端更簡單。

  2. 它的使用方法是定義一個服務介面,然後在上面新增註解。

  3. OpenFeign 也支援可插拔式的編碼器解碼器

  4. Spring Cloud 對 OpenFeign 進行了封裝使其支援了 Spring MVC 標註註解 和 HttpMessageConverters

  5. OpenFeign 可以與 Eureka 和 Ribbon 組合使用以支援負載均衡。

  6. OpenFeign 官網地址: https://github.com/spring-cloud/spring-cloud-openfeign

簡單的說:就是一個 Web Service 客戶端訪問的,轉發的一個元件,可以實現 Server 叢集的通訊,簡化 Web Service 客戶端

在這裡插入圖片描述

1.1 Feign 和 OpenFeign 區別

Feign:

  • Feign 是Spring Cloud 元件中的一個輕量級 RESTful的HTTP服務客戶端
  • Feign 內建了Ribbon ,用來做客戶端負載均衡,去呼叫服務註冊中心的服務
  • Feign 的使用方式是: 使用Feign的註解定義介面,呼叫服務註冊中心的服務。
  • Feign 支援的註解和用法參考官方文件: https://github.com/OpenFeign/feign
  • Feign 本身不支援Spring MVC的註解 ,它有一套自己的註解,所以大部分市場開發已經不使用 Feign 了。
  • 引入依賴:
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

OpenFeign:

  • OpenFeign 是 Spring Cloud 在 Feign的基礎上支援了Spring MVC 的註解,如 @RequestMapping等等
  • OpenFeign 的 @FeignClient 可以解析 Spring MVC 的 @RequestMapping 註解下的介面
  • OpenFeign 透過動態代理的方式產生實現類,實現類中做負載均衡並呼叫其他服務。
    引入依賴:
   <!--  引入 openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  • 精簡一句話: OpenFeign 就是在 Feign基礎上做了加強,有些程式設計師為了方便,說 Feign 就是OpenFeign

2. OpenFeign 應用例項

需求分析&圖解

示意圖:

在這裡插入圖片描述

  1. 建立服務消費模組 - 透過 OpenFeigen 實現遠端呼叫

參考 member-service-consumer-80 建立 member-service-consumer-openfeign-80(具體步 驟參考以前)

在這裡插入圖片描述

  1. pom.xml 檔案當中,匯入相關的 jar 依賴。特別是這裡:我們的主角openFeign

在這裡插入圖片描述

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

完整的 pom.xml 檔案資訊:

<?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>e-commerce-center</artifactId>
        <groupId>com.rainbowsea</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>member-service-consumer-openfeign-80</artifactId>


    <!--    引入相關的依賴:我們引入了當前所需要的依賴,後面如果有其它的需要,再靈活新增-->
    <dependencies>

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

        <!--        引入 web-starter 說明:我們使用版本仲裁(從父專案繼承了版本)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--1. starter-actuator 是spring boot 程式的監控系統,可以實現健康檢查,info 資訊等
         2. 訪問http://localhost:80/actuator 可以看到相關連結,還可以做相關配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>


        <!--        lombok 引入-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

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

        <!--        引入我們自己對 bean 封裝成 api 的模組內容-->
        <dependency>
            <groupId>com.rainbowsea</groupId>
            <artifactId>e_commerce_center-common-api</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!-- 引入 eureka-client 依賴  -->
        <!--        注意:存在一個 starter 不要選錯了-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

</project>
  1. 在 resourse 目錄下,建立 application.yml 進行一些相關的配置資訊, 內容如下:

在這裡插入圖片描述

server:
  port: 80
spring:
  application:
    name: member-service-consumer-openfeign-80

# 配置 eureka client 注意,因為這裡該模組是作為 client 客戶端的角色的,所有要將自己client的資訊傳送給 Server 當中去的
eureka:
  client:
    register-with-eureka: true # 表示將自己註冊到 Eureka-Server 當中
    fetch-registry: true # 表示將資訊傳送到 Eureka-Server 當中
    service-url:
      # 表示將自己註冊到那個 eureka-server
      #      defaultZone: http://localhost:9001/eureka
      # 將本微服務註冊到多個 eureka - server 當中,使用逗號間隔即可
      defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/

  1. 建立該模組 member-service-consumer-openfeign-80 的主啟動類,也就是場景啟動器。

在:建立包com.rainbowsea.springcloud ,建立名為 MemberConsumerOpenfeignApplication80的主啟動類,如下圖所示:

在這裡插入圖片描述

package com.rainbowsea.springcloud;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient  // 表示作為 Eureka Client 角色
@EnableFeignClients  // 啟動 OpenFeignClient
public class MemberConsumerOpenfeignApplication80 {


    public static void main(String[] args) {

        SpringApplication.run(MemberConsumerOpenfeignApplication80.class, args);
    }
}

新增主啟動類之後,我們可以測試一下,是否成功將該模組member-service-consumer-openfeign-80 註冊到了 Eureka Server 當中去了。

在這裡插入圖片描述

注意:下面的操作就是:是 OpenFeign 的核心內容了。

  1. 在該member-service-consumer-openfeign-80 模組當中建立一個com.rainbowsea.springcloud.service 包,在該包當中建立一個 MemberFeignService 介面,注意注意是介面interface 不是類。如下圖所示:

在這裡插入圖片描述

package com.rainbowsea.springcloud.service;


import com.rainbowsea.springcloud.entity.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
public interface MemberFeignService {


}

然後我們需要將其中,我們 member-service-consumer-openfeign-80 模組是作為 Eureka Client 客戶端存在的,這裡使用 OpenFeign 簡化客戶端,我們還需將 ,我們 OpenFeigin(也就是客戶端,也就是 Eureka Client ) 想要呼叫的哪個 provider service(伺服器/服務叢集) 處理我們的業務,這裡我們是服務叢集 ,這裡我們有兩個 privoid service 可以處理我們所需的業務,如下圖所受:分別為:

member-service-provider-10000,member-service-provider-10002 這兩個服務(這兩個服務,是已經相互註冊好了,配置為了服務叢集了 )

在這裡插入圖片描述

這裡我們在MemberFeignService 介面類上使用 @FeignClient註解標註,我們這個 OpenFeigin(也就是客戶端,也就是 Eureka Client ) 想要呼叫的哪個 provider service(伺服器/服務叢集) 處理我們的業務。如下圖所示:

在這裡插入圖片描述

package com.rainbowsea.springcloud.service;


import com.rainbowsea.springcloud.entity.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
//這裡 MEMBER-SERVICE-PROVIDER 就是 Eureka Server 服務提供方註冊的名稱
@FeignClient(value = "MEMBER-SERVICE-PROVIDER")  // 這個 value 值就是,對應我們想要訪問的 provider(提供服務/服務叢集)的 name 名稱
public interface MemberFeignService {

}

同時我們還需要在 MemberFeignService 介面當中定義一個方法。

注意這個方法,必須必須和你 OpenFeigin(也就是客戶端,也就是 Eureka Client ) 想要呼叫的哪個 provider service(伺服器/服務叢集) 中的處理對應業務的哪個方法,保持一致(許可權修飾符一致,Http請求方式(包括了所對應的請求對映路徑)一致,引數型別,引數個數一致,返回值型別也是一致的,方法名可以不一致(但強烈建議也保持一致)),所以強烈建議,直接從對應的 provider service 當中複製過來即可。如下圖:我們使用的是 getMemberById 根據 id 查詢的業務處理。我們只需將其方法名複製過來即可。

在這裡插入圖片描述

package com.rainbowsea.springcloud.service;


import com.rainbowsea.springcloud.entity.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
//這裡 MEMBER-SERVICE-PROVIDER 就是 Eureka Server 服務提供方註冊的名稱
@FeignClient(value = "MEMBER-SERVICE-PROVIDER")  // 這個 value 值就是,對應我們想要訪問的 provider(提供服務/服務叢集)的 name 名稱
public interface MemberFeignService {



    // 注意:這裡定義方法-就是遠端呼叫的介面,建議複製過來

    /*
    1.遠端呼叫的方式是get
    2.遠端呼叫的 url http://MEMBER-SERVICE-PROVIDER(註冊到服務當中的別名)/member/get/{id}
    3.MEMBER-SERVICE-PROVIDER 就是服務提供方法 Eureka Server 註冊的服務
    4. openfeign 會根據負載均衡決定呼叫 10000/10002 -預設是輪詢
    5.因為openfeign 好處是支援了 spring mvc 註解 + 介面解構
    6. 想要使用 OPFeign 需要在對應場景啟動器的位置配置上: @EnableFeignClients  // 啟動 OpenFeignClient

     */
    @GetMapping("/member/get/{id}")
    Result getMemberById(@PathVariable("id") Long id);


}

最後,我們在當前 member-service-consumer-openfeign-80 模組也就是我們的 OpenFeigin(也就是客戶端,也就是 Eureka Client ) 編寫控制器,在 com.rainbowsea.springcloud.controller 包下,編寫對應的控制器。如下圖所示:

在這裡插入圖片描述

在這裡插入圖片描述

package com.rainbowsea.springcloud.controller;


import com.rainbowsea.springcloud.entity.Result;
import com.rainbowsea.springcloud.service.MemberFeignService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class MemberConsumerFeignController {

    // 裝配MemberFeignService
    @Resource
    private MemberFeignService memberFeignService;

    @GetMapping("/member/consumer/openfeign/get/{id}")
    public Result getMemberById(@PathVariable("id") Long id) {
        // 呼叫介面中的方法
        return memberFeignService.getMemberById(id);

    }
}

  • 特別說明,因為我們的 OpenFeign 就是一個透過介面+註解的方式作為Eureka Client 客戶端,呼叫其中 Service 伺服器
  • Openfeign 的使用的特點:微服務介面+@FeignClient ,使用介面進行解耦(簡單的說:就是使用介面呼叫對應 provider 提供服務的叢集)

測試,啟動伺服器

瀏覽器輸入 : http://localhost/member/consumer/openfeign/get/1

觀察訪問的 10000/10002 埠的服務是輪詢的

在這裡插入圖片描述

2.2 注意事項和細節

  • @FeignClient(value = "MEMBER-SERVICE-PROVIDER") // 這個 value 值就是,對應我們想要訪問的 provider(提供服務/服務叢集)的 name 名稱 所以:注意不要將提供註冊的名稱,寫錯了

在這裡插入圖片描述

  • 介面方法上的: value 是不能亂寫的,遠端呼叫的url為 : 對應你想要呼叫哪個 provider 名稱的別名/名稱 http://MEMBER-SERVICE-PROVIDER/member/get/{id};介面上的方法,也必須與呼叫的 provider 當中的方法保持一致:

在這裡插入圖片描述

3. OpenFeign 內建的“日誌配置” 操作

說明 OpenFeign 提供了日誌列印功能,可以透過配置來調整日誌級別,從面對 OpenFeign 介面的呼叫情況進行監控和輸出。

日誌級別:

  1. NONE: 預設的,不顯示任何日誌
  2. BASIC: 僅記錄請求方式,URL,響應狀態碼及執行時間
  3. HEADERS:除了 BASIC 中定義的資訊之外,還有請求和響應的頭資訊
  4. FULL: 除了HEADERS 中定義的資訊之外,還有請求和響應的正文及後設資料

常見的日誌級別有 5 種,分別是 error、warn、info、debug、trace

  1. error:錯誤日誌,指比較嚴重的錯誤,對正常業務有影響,需要運維配置監控的;
  2. warn:警告日誌,一般的錯誤,對業務影響不大,但是需要開發關注;
  3. info:資訊日誌,記錄排查問題的關鍵資訊,如呼叫時間、出參入參等等;
  4. debug:用於開發 DEBUG 的,關鍵邏輯裡面的執行時資料;
  5. trace:最詳細的資訊,一般這些資訊只記錄到日誌檔案中。

3.1 OpenFeign 配置日誌-應用例項

在member-service-consumer-openfeign-80 建立 com.Rainbowsea.springcloud.config.OpenFeignConfig.java 類

在這裡插入圖片描述

package com.rainbowsea.springcloud.config;


import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class OpenFeignConfig {


    @Bean
    public Logger.Level loggerLever() {
        // /日誌級別指定為 FULL
        return Logger.Level.FULL;
    }
}

member-service-consumer-openfeign-80 模組當中修改 application.yml 進行配置我們是對哪個類進行日誌列印資訊,以及列印配置的日誌資訊的級別

在這裡插入圖片描述


logging:
  level:
    # 對 MemberFeignService 介面呼叫過程列印資訊-Debug
    com.rainbowsea.springcloud.service.MemberFeignService: debug


server:
  port: 80
spring:
  application:
    name: member-service-consumer-openfeign-80

# 配置 eureka client 注意,因為這裡該模組是作為 client 客戶端的角色的,所有要將自己client的資訊傳送給 Server 當中去的
eureka:
  client:
    register-with-eureka: true # 表示將自己註冊到 Eureka-Server 當中
    fetch-registry: true # 表示將資訊傳送到 Eureka-Server 當中
    service-url:
      # 表示將自己註冊到那個 eureka-server
      #      defaultZone: http://localhost:9001/eureka
      # 將本微服務註冊到多個 eureka - server 當中,使用逗號間隔即可
      defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/

logging:
  level:
    # 對 MemberFeignService 介面呼叫過程列印資訊-Debug
    com.rainbowsea.springcloud.service.MemberFeignService: debug

測試
瀏覽器: http://localhost/member/consumer/openfeign/get/1

IDEA 後端檢視列印的顯示的日誌資訊:

在這裡插入圖片描述

4. OpenFeign 超時時間設定操作

OpenFeign 超時: 我們先來看如下一個問題:

我們模擬網路異常,在 member-service-provider-10000member-service-provider-10002 兩個 service 服務提供方當中的 getMemberById 方法,模擬超時 ,這裡暫停 5秒。

   // 模擬超時 ,這裡暫停 5秒
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (Exception e) {
            e.printStackTrace();
        }

在這裡插入圖片描述

瀏覽器訪問 http://localhost/member/consumer/openfeign/get/1

測試效果:

瀏覽器顯示: Read timed out executing GET http://MEMBER-SERVICE-PROVIDER/member/get/1
IDEA後端顯示: java.net.SocketTimeoutException: Read timed out
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is feign.RetryableException: Read timed out executing GET http://MEMBER-SERVICE-PROVIDER/member/get/1] with root cause

在這裡插入圖片描述

在這裡插入圖片描述

原因分析: OpenFeign 預設超時時間 1 秒鐘 ,即等待返回結果 1 秒,超過了 1 秒,則會報錯。

設定超時時間

說明: 在某些情況下,一個服務呼叫時間可能要超過 1 秒,就需要重新設定超時時間。

這裡我們設定超時時間設定為:8秒,而我們模擬的是 5秒,5 秒小於 8 秒,可以還在超時時間的範圍內,可以被訪問。

對於 OpenFeign 超時時間,我們需要在 application.yaml 檔案當中進行配置。 如下圖所示:

# OpenFeign 超時
ribbon:
#  #設定 feign 客戶端超時時間(openFeign 預設支援 ribbon) #指的是建立連線後從伺服器讀取到可用資源所用的時間,
#  #時間單位是毫秒
  ReadTimeout: 8000
#  #指的是建立連線所用的時間,適用於網路狀況正常的情況下,
#  #兩端連線所用的時間
  ConnectTimeout: 8000

在這裡插入圖片描述

server:
  port: 80
spring:
  application:
    name: member-service-consumer-openfeign-80

# 配置 eureka client 注意,因為這裡該模組是作為 client 客戶端的角色的,所有要將自己client的資訊傳送給 Server 當中去的
eureka:
  client:
    register-with-eureka: true # 表示將自己註冊到 Eureka-Server 當中
    fetch-registry: true # 表示將資訊傳送到 Eureka-Server 當中
    service-url:
      # 表示將自己註冊到那個 eureka-server
      #      defaultZone: http://localhost:9001/eureka
      # 將本微服務註冊到多個 eureka - server 當中,使用逗號間隔即可
      defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/

logging:
  level:
    # 對 MemberFeignService 介面呼叫過程列印資訊-Debug
    com.rainbowsea.springcloud.service.MemberFeignService: debug

# OpenFeign 超時
ribbon:
#  #設定 feign 客戶端超時時間(openFeign 預設支援 ribbon) #指的是建立連線後從伺服器讀取到可用資源所用的時間,
#  #時間單位是毫秒
  ReadTimeout: 8000
#  #指的是建立連線所用的時間,適用於網路狀況正常的情況下,
#  #兩端連線所用的時間
  ConnectTimeout: 8000

瀏覽器輸出: http://localhost/member/consumer/openfeign/get/1, 不會出現超時,會輪詢訪問 10000/10002

在這裡插入圖片描述

5. 補充:spring-boot-starter-actuator 是 spring boot 程式的監控系統,可以實現健康檢查

當我們在 pom.xml 當中新增了 spring-boot-starter-actuator 的依賴 jar ,就就可以使用該 監控系統了。不需要其他的配置

spring-boot-starter-actuator 是spring boot 程式的監控系統,可以實現健康檢查,info 資訊等

訪問http://localhost:80/actuator 可以看到相關連結,還可以做相關配置。

spring-boot-starter-actuator 訪問的語法連結:url地址+自身模組對應的埠號/actuator

在這裡插入圖片描述

6. 總結:

  1. OpenFeign 是個宣告式 WebService 客戶端,使用 OpenFeign 讓編寫 Web Service客戶端更簡單。
  2. Feign 和 OpenFeign 區別
  3. Openfeign 的使用的特點:微服務介面+@FeignClient ,使用介面進行解耦(簡單的說:就是使用介面呼叫對應 provider 提供服務的叢集)
  4. OpenFeign 操作配置的注意事項和細節:
    1. Openfeign 的使用的特點:微服務介面+@FeignClient ,使用介面進行解耦(簡單的說:就是使用介面呼叫對應 provider 提供服務的叢集)
    2. 介面方法上的: value 是不能亂寫的,遠端呼叫的url為 : 對應你想要呼叫哪個 provider 名稱的別名/名稱 http://MEMBER-SERVICE-PROVIDER/member/get/{id};介面上的方法,也必須與呼叫的 provider 當中的方法保持一致:
  5. OpenFeign 內建的“日誌配置”:OpenFeign 提供了日誌列印功能,可以透過配置來調整日誌級別,從面對 OpenFeign 介面的呼叫情況進行監控和輸出。
  6. OpenFeign 超時時間設定操作
  7. spring-boot-starter-actuator 是 spring boot 程式的監控系統,可以實現健康檢查,spring-boot-starter-actuator 是spring boot 程式的監控系統,可以實現健康檢查,info 資訊等

spring-boot-starter-actuator 訪問的語法連結:url地址+自身模組對應的埠號/actuator

7. 最後:

“在這個最後的篇章中,我要表達我對每一位讀者的感激之情。你們的關注和回覆是我創作的動力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會將你們的鼓勵留在心底,繼續在其他的領域奮鬥。感謝你們,我們總會在某個時刻再次相遇。”

在這裡插入圖片描述

相關文章