Spring Cloud OpenFeign 的使用及踩坑指南

来源:https://www.cnblogs.com/subbubble/archive/2023/08/04/17605678.html
-Advertisement-
Play Games

## 目錄 - [Feign 和OpenFeign](#Feign-和OpenFeign) - [Feign](#Feign) - [OpenFeign](#OpenFeign) - [openFeign的優勢](#openFeign的優勢) - [OpenFeign應用](#OpenFeign應用 ...


目錄

Feign 和OpenFeign

Feign

Feign是Spring Cloud組件中的一個輕量級RESTful的HTTP服務客戶端Feign內置了Ribbon,用來做客戶端負載均衡,去調用服務註冊中心的服務。

Feign的使用方式是:使用Feign的註解定義介面,調用這個介面,就可以調用服務註冊中心的服務Feign本身不支持Spring MVC的註解,它有一套自己的註解

OpenFeign

OpenFeign是Spring Cloud 在Feign的基礎上支持了Spring MVC的註解,如@RequesMapping等,是一個輕量級的Http封裝工具對象,大大簡化了Http請求,使得我們對服務的調用轉換成了對本地介面方法的調用。

OpenFeign 的 @FeignClient 可以解析SpringMVC的 @RequestMapping註解下的介面,並通過動態代理的方式產生實現類,實現類中做負載均衡並調用其他服務

openFeign的優勢

  1. 集成了Ribbon的負載均衡功能
  2. 集成Hystrix的熔斷器功能
  3. 支持請求壓縮
  4. 大大簡化了遠程調用的代碼,同時功能還增強啦
  5. 以更加優雅的方式編寫遠程調用代碼,並簡化重覆代碼

OpenFeign應用

1. 導入依賴

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

2. 使用

創建Feign介面

@FeignClient(value = "xx-template-service")//value = "xx-template-service"指定服務的名字
public interface DriverFeign {

  /** 
   * demo feign 介面
   */
  @PutMapping(value = "/driver/status")
  Driver status(String id, Integer status);
}

Feign會通過動態代理,幫我們生成實現類。

註解@FeignClient聲明Feign的客戶端,註解value指明服務名稱介面定義的方法,採用SpringMVC的註解。Feign會根據註解幫我們生成URL地址

FeignClient 註解參數

  • name/value:指定FeignClient的名稱,如果項目使用了Ribbon,name屬性會作為微服務的名稱,用於服務發現
  • contextId:指定beanID
  • url: url一般用於調試,可以手動指定@FeignClient調用的地址
  • decode404:當發生http 404錯誤時,如果該欄位位true,會調用decoder進行解碼,否則拋出FeignException
  • configuration: Feign配置類,可以自定義Feign的Encoder、Decoder、LogLevel、Contract
  • fallback: 定義容錯的處理類,當調用遠程介面失敗或超時時,會調用對應介面的容錯邏輯,fallback指定的類必須實現@FeignClient標記的介面
  • fallbackFactory: 工廠類,用於生成fallback類示例,通過這個屬性我們可以實現每個介面通用的容錯邏輯,減少重覆的代碼
  • path: 定義當前FeignClient的統一首碼

註意事項

  1. 在使用fallback、fallbackFactory屬性時,需要使用@Component註解,保證fallback類被Spring容器掃描到
  2. 在使用FeignClient時,Spring會按name創建不同的ApplicationContext,通過不同的Context來隔離FeignClient的配置信息, 在使用配置類時,不能把配置類放到Spring App Component scan的路徑下,否則,配置類會對所有FeignClient生效.

啟用OpenFeign

我們需要在服務的啟動類上開啟 OpenFeign ,只需要在 **Application 啟動類上添加 @EnableFeignClients即可。

3. 日誌配置

logging:
  level:
    xx.template.cloud.web.service.feign.ServiceServiceFeign: debug

通過loggin.level.xx=debug來設置日誌級別。然而這個對Feign客戶端不會產生效果。因為@FeignClient註解修飾的客戶端在被代理時,都會創建一個新的Feign.Logger實例。我們需要額外指定這個日誌的級別才可以。

  /** 
   * feign 日誌級別配置
   * @return 
   */
  @Bean
  public Logger.Level feignLoggerLevel(){
    return Logger.Level.FULL;
  }

或者在配置文件中配置

feign: 
  client:
    config:
      # 全局配置
      default:
        loggerLevel: full

Feign支持4種級別:
NONE:不記錄任何日誌,預設值
BASIC:僅記錄請求的方法,URL以及響應狀態碼和執行時間
HEADERS:在BASIC基礎上,額外記錄了請求和響應的頭信息
FULL:記錄所有請求和響應的明細,包括頭信息、請求體、元數據

4. 數據壓縮

用戶在網路請求過程中,如果網路不佳、傳輸數據過大,會造成體驗差的問題,我們需要將傳輸數據壓縮提升體驗。SpringCloud OpenFeign支持對請求和響應進行GZIP壓縮,以減少通信過程中的性能損耗。

在客戶端中配置數據壓縮

feign:
  compression:
    request:
     enabled: true # 開啟請求壓縮
    response:
     enabled: true # 開啟響應壓縮

也可以對請求的數據類型,以及觸發壓縮的大小下限進行設置

feign:
  compression:
    request:
      enabled: true # 開啟請求壓縮
      mime-types: text/html,application/xml,application/json # 設置壓縮的數據類型
      min-request-size: 2048 # 設置觸發壓縮的大小下限
      #以上數據類型,壓縮大小下限均為預設值
      response:
        enabled: true # 開啟響應壓縮

OpenFeign高級應用

OpenFeign熔斷降級的兩種方式-降級方法和降級工廠

首先在配置文件中配置如下,開啟熔斷降級

feign.hystrix.enabled=true
  1. Feign 定義降級方法

    feign介面定義

    /**
     * FeignClient 註解的 fallback 屬性指定降級類
     */
    @FeignClient(name = "xx-template-cloud-service", fallback = ServiceServiceFeignFallBack.class)
    public interface ServiceServiceFeign {
    
        @GetMapping("/order/getOrder")
        Result getOrder(String id);
    }
    
    

    feign介面降級方法定義

    @Slf4j
    @Component
    class ServiceServiceFeignFallBack implements ServiceServiceFeign {
    
        @Override
        public Result getOrder(String id) {
            log.error("Feign介面熔斷 熔斷方式:ServiceServiceFeignFallBack");
            return Result.error("500", "Feign介面熔斷");
        }
    }
    
  2. Feign 定義降級工廠

    feign介面定義

    /**
     * FeignClient 註解的 fallback 屬性指定降級類
     */
    @FeignClient(name = "xx-template-cloud-service", fallback = UserCenterFeignClientFallbackFactory.class)
    public interface ServiceServiceFeign {
    
        @GetMapping("/order/getOrder")
        Result getOrder(String id);
    }
    
    

    feign介面降級工廠定義

    @Component
    @Slf4j
    class UserCenterFeignClientFallbackFactory implements FallbackFactory<ServiceServiceFeign> {
    
        @Override
        public ServiceServiceFeign create(Throwable cause) {
            return new ServiceServiceFeign() {
                @Override
                public Result getOrder(String id) {
                    log.error("Feign介面熔斷,熔斷方式:UserCenterFeignClientFallbackFactory");
                    return Result.error("500", "Feign介面熔斷");
                }
            };
        }
    }
    

踩坑指南

坑一:Http Client

OpenFeign預設使用jdk自帶的HttpURLConnection,我們知道HttpURLConnection沒有連接池、性能和效率比較低,如果採用預設,很可能會遇到性能問題導致系統故障

  1. 可以採用Apache HttpClient

    註意feign-httpclient的版本,如果和Open Feign 不相容可能會報original request is required異常

    <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-httpclient</artifactId>
        <version>10.10.1</version>
    </dependency>
    
    feign.httpclient.enabled=true
    
  2. 也可以採用OkHttpClient

    <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-okhttp</artifactId>
        <version>10.2.0</version>
    </dependency>
    
    feign.okhttp.enabled=true
    

ribbon中的Http Client

通過OpenFeign作為註冊中心的客戶端時,預設使用Ribbon做負載均衡,Ribbon預設也是用jdk自帶的HttpURLConnection,需要給Ribbon也設置一個Http client,比如使用okhttp,在properties文件中增加下麵配置

ribbon.okhttp.enabled=true

坑二:全局超時時間

OpenFeign可以設置超時時間,簡單粗暴,設置一個全局的超時時間。如果不配置超時時間,預設是連接超時10s,讀超時60s。

feign.client.config.default.connectTimeout=2000
feign.client.config.default.readTimeout=60000

但是如果某個服務的併發量很高,服務的超時時間過長會導致占用大量連接資源,導致系統崩潰,要防止這樣的故障發生,最好的做法就是給服務單獨設置超時時間。

當然,如果開啟熔斷後,不配置hystrix和ribbon的超時時間,那麼Hystrix與ribbon的預設請求超時時間都是1秒,建議配置Hystrix的超時時間要大於ribbon的超時時間,否則會在介面調用還未完成的時候直接進入回調方法。

# 開啟熔斷
feign.hystrix.enabled: true


坑三:單服務設置超時時間

上文所述,對單個服務設置超時時間。

feign.client.config.serviceA.connectTimeout=2000
feign.client.config.serviceA.readTimeout=60000

但是如果serviceA中有多個介面,其中X介面又調用serviceB的Feign介面,為了保證X介面請求不被單服務超時時間影響,需要單獨對X介面設置超時時間。

幾個組件的關係

hystrix+ribbon。hystrix在最外層,然後再到Ribbon,最後裡面的是http請求。所以說。hystrix的熔斷時間必須大於ribbon的 ( ConnectTimeout + ReadTimeout )。而如果ribbon開啟了重試機制,還需要乘以對應的重試次數(註意這裡的重試可以是ribbon的重試也可能是feign的重試),保證在Ribbon里的請求還沒結束時,Hystrix的熔斷時間不會超時。

遇到的問題

1. 使用Spring MVC註解,但請求方式不正確

  • 參數沒有通過註解指定,此時的參數會自動封裝到body中,Feign檢測到body裡面有請求參數就會預設使用POST請求。
  • Feign預設使用的是POST方法,如果想使用GET方法,需要在配置文件中設置spring.cloud.openfeign.client.config.default.method.name=get。
  • 如果使用了Spring Cloud Netflix Feign,那麼可能是因為您的應用程式使用了Spring Cloud Netflix Ribbon來處理HTTP負載均衡。在這種情況下,您需要確保Ribbon的配置正確,並且不會影響Feign的GET請求。

2. 使用nacos做註冊中心,Feign調用時拉取的服務列表為空

我用的spring cloud版本是Hoxton.SR8

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR8</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

原因是Feign 在spring cloud Hoxton.M2版本之後,不再使用ribbon,所以我們在pom文件中還需要導入loadbalancer依賴,併排除掉nacos的ribbon依賴。

        <!--nacos-discovery-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2021.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>

併在配置文件中添加


spring.cloud.loadbalancer.ribbon.enabled: false

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 選擇哪種分配方式由Java堆是否規整決定,而Java堆是否規整又由所採用的垃圾收集器是否帶有壓縮整理功能決定。因此,在使用Serial、ParNew等帶Compact過程的收集器時,系統採用的分配演算法是指針碰撞,而使用CMS這種基於Mark-Sweep演算法的收集器時,通常採用空閑列表。這兩種對象訪問... ...
  • 環境: centos7.9 tomcat9 jdk1.8 # 一.阿裡雲申請 [免費SSL](https://yundunnext.console.aliyun.com/?spm=5176.21213303.782131.4.304053c9wUb2BP&p=cas#/certExtend/free ...
  • python中的多線程其實並不是真正的多線程,如果想要充分地使用多核CPU資源,在python中大部分情況需要使用多進程。 python提供了非常好用的多進程包Multiprocessing,只需要定義一個函數,python會完成其它所有事情。藉助這個包,可以輕鬆完成從單進程到併發執行的轉換。 mu ...
  • Lucas定理: 主要是求$C_{n}^{m}$在模$p$情況下($mod \, p$)(一般$p$較小,而$n,m$較大的情況) 公式: $ C_{n}^{m} ≡ C_{n \, mod \, p}^{m \, mod \, p} \times C_{n/p}^{m/p} (mod \, p) ...
  • ## 測試 Spring提供了一組測試工具,可以輕鬆地測試Spring應用程式的各個組件,包括控制器、服務、存儲庫和其他組件。它具有豐富的測試註釋、實用程式類和其他功能,以幫助進行單元測試、集成測試等。 ### JPA測試 Spring JPA(Java Persistence API)是一個庫,它 ...
  • ## JAVA函數式編程 ### 函數式編程的背景和概念 維基百科:**函數式編程**,或稱**函數程式設計**、**泛函編程**(英語:Functional programming),是一種[編程範型](https://zh.wikipedia.org/wiki/編程範型),它將[電腦運算](ht ...
  • @[TOC] # Scala的基本使用 ## 一、基礎語法 ### 1.1 變數 #### 1.1.1 var和val Scala中的變數分為兩種: 可變var:可以隨時修改var聲明的變數的值 不可變val:val聲明的變數,值不能被修改,否則會報錯:error: reassignment to ...
  • 最近在新項目的開發過程中,遇到了個問題,需要將一些異常的業務流程返回給前端,需要提供給前端不同的響應碼,前端再在次基礎上做提示語言的國際化適配。這些異常流程涉及業務層和控制層的各個地方,如果每個地方都寫一些重覆代碼顯得很冗餘。 然後查詢解決方案時發現了@ControllerAdvice這個註解,可以 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...