【spring】spring中的retry重試機制; resilience4j熔斷限流教程;springboot整合retry+resilience4j教程

在調用三方接口時,我們一般要考慮接口調用失敗的處理,可以通過spring提供的retry來實現;如果重試幾次都失敗了,可能就要考慮降級補償了;

有時我們也可能要考慮熔斷,在微服務中可能會使用sentinel來做熔斷;在單體服務中,可以使用輕量化的resilience4j來做限流或熔斷

文章目錄

  • maven依賴
  • retry重試機制
  • circuitbreaker 熔斷機制
  • ratelimiter限流機制

maven依賴

        <!-- web項目jar包 包含starter、spring、webmvc 等--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- aop --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!-- spring提供的重試機制  需要@EnableRetry 注解開啟 --><dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId></dependency><!-- actuator 有健康檢查、監控管理等生產環境需要使用到的功能 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- resilience4j 如果是Spring Boot 2.x項目,使用resilience4j-spring-boot2替代 --><dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-spring-boot3</artifactId><version>2.2.0</version></dependency>

retry重試機制

  1. 引入了retry相關依賴后,需要開啟@EnableRetry
    例如:
@SpringBootApplication
@MapperScan
@EnableRetry
public class Application {public static void main(String[] args) {SpringApplication.run(Application .class, args);}}
  1. 在要重試的方法加上@Retryable注解

例如:

@RestController
@RequestMapping("/test/retry")
public class RetryController {@Retryable(value = Exception.class, maxAttempts = 3,backoff = @Backoff(delay = 1000,multiplier = 1.5))@GetMapping("/test")public String test() {System.out.println("do-something:"+ LocalDateTime.now());long l = System.currentTimeMillis();System.out.println(count++);int a = 0;System.out.println( l % 2 == 0);if (l % 2 == 0) {a = 1 / 0;}System.out.println("res=" + a+"  "+LocalDateTime.now());return "200";}}

參數解釋:

value:拋出指定異常才會重試
noRetryFor:指定不處理的異常
maxAttempts:最大重試次數,默認3次
backoff:重試等待策略,默認使用@Backoff,
@Backoff的value(相當于delay)表示隔多少毫秒后重試,默認為1000L;
multiplier(指定延遲倍數)默認為0,表示固定暫停1秒后進行重試。

tips: multiplier 的實際意義 當我們調用某個接口失敗時,如果緊接著馬上又調用,大概率接口仍然是失敗的,multiplier是一個遞延時間,可以起到調用間隔越來越大的作用。

  1. 如果重試到最大次數仍然失敗,希望有降級處理 代碼則變成:
@RestController
@RequestMapping("/test/retry")
public class RetryController {@Retryable(value = Exception.class, maxAttempts = 3,backoff = @Backoff(delay = 1000,multiplier = 1.5))@GetMapping("/test")public String test() {System.out.println("do-something:"+ LocalDateTime.now());long l = System.currentTimeMillis();System.out.println(count++);int a = 0;System.out.println( l % 2 == 0);if (l % 2 == 0) {a = 1 / 0;}System.out.println("res=" + a+"  "+LocalDateTime.now());return "200";}/*** @Recover 的返回類型,必須跟 @Retryable修飾的方法返回值一致。*/@Recoverpublic String recoverTest(ArithmeticException e) {System.out.println("test模擬記錄錯誤日志"+e.getMessage());return "test降級處理";}}
  1. 如果一個類中,有多個方法呢?@Retryable和@Recover是怎么對應的?(即@Recover是怎么判斷 來自哪個方法):
@Recover方法必須與@Retryable方法在同一個Spring管理的Bean中;確保AOP代理生效。
當存在多個可能的@Recover方法時,Spring按以下優先級選擇:
異常類型最具體的方法(如子類異常優先于父類)。
返回類型最匹配的方法(避免類型轉換錯誤)。
參數列表更匹配的方法(如包含原方法參數)

例如:

@RestController
@RequestMapping("/test/retry")
public class RetryController {int count = 0;String noete = """@Recover方法必須與@Retryable方法在同一個Spring管理的Bean中,確保AOP代理生效。當存在多個可能的@Recover方法時,Spring按以下優先級選擇:異常類型最具體的方法(如子類異常優先于父類)。返回類型最匹配的方法(避免類型轉換錯誤)。參數列表更匹配的方法(如包含原方法參數)value:拋出指定異常才會重試noRetryFor:指定不處理的異常maxAttempts:最大重試次數,默認3次backoff:重試等待策略,默認使用@Backoff,@Backoff的value(相當于delay)表示隔多少毫秒后重試,默認為1000L;multiplier(指定延遲倍數)默認為0,表示固定暫停1秒后進行重試。""";@Retryable(value = Exception.class, maxAttempts = 3,backoff = @Backoff(delay = 1000,multiplier = 1.5))@CircuitBreaker(name = "backendA",fallbackMethod = "fallback")@GetMapping("/test")public String test() {System.out.println("do-something:"+ LocalDateTime.now());long l = System.currentTimeMillis();System.out.println(count++);int a = 0;System.out.println( l % 2 == 0);if (l % 2 == 0) {a = 1 / 0;}System.out.println("res=" + a+"  "+LocalDateTime.now());return "200";}@Retryable(value = Exception.class, maxAttempts = 3,backoff = @Backoff(delay = 1000,multiplier = 1.5))@GetMapping("/test1")public String test1() {System.out.println("do-something:"+ LocalDateTime.now());// NumberFormatExceptionInteger a = Integer.parseInt(null);System.out.println("res=" + a +"  "+LocalDateTime.now());return "200";}@Retryable(value = Exception.class, maxAttempts = 3,backoff = @Backoff(delay = 1000,multiplier = 1.5))@GetMapping("/test2")public String test2(String name) {System.out.println("do-something:"+ LocalDateTime.now());int a = 1 / 0;System.out.println("res=" + a+"  "+LocalDateTime.now());return "200";}/*** @Recover 的返回類型,必須跟 @Retryable修飾的方法返回值一致。*/@Recoverpublic String recoverTest(ArithmeticException e) {System.out.println("test模擬記錄錯誤日志"+e.getMessage());return "test降級處理";}@Recoverpublic String recoverTest1(NumberFormatException e) {System.out.println("test1模擬記錄錯誤日志"+e.getMessage());return "test1降級處理";}@Recoverpublic String recoverTest2(ArithmeticException e,String name) {System.out.println("test2模擬記錄錯誤日志"+e.getMessage());return "test2降級處理";}}

circuitbreaker 熔斷機制

  1. yml中配置
# resilience4j (輕量級熔斷)
resilience4j:circuitbreaker:instances:# 自定義的熔斷名稱backendA:sliding-window-type: count_based # 默認是count, 還可以配置 TIME_BASED sliding-window-size則表示最近幾秒sliding-window-size: 4 # 只看最近四次調用(為了方便測試)minimum-number-of-calls: 1 #只需一次調用就開始評估failure-rate-threshold: 50 # 失敗率超過50 就開啟熔斷 (開啟熔斷后,后面請求就直接進入熔斷了)wait-duration-in-open-state: 5s # 開啟后5s進入半開狀態  (半開啟是個靈活的狀態,后續服務恢復就不用進入熔斷了)permitted-number-of-calls-in-half-open-state: 2 # 半開狀態允許有兩次測試調用 如果低于 failure-rate-threshold 失敗率 ,則不會進入熔斷automatic-transition-from-open-to-half-open-enabled: true # 半開啟狀態
  1. 代碼中使用,fallback如果是只接收限流異常 則定義成CallNotPermittedException,如果定義成Exception , 則只要發生異常就會進入方法(不會基于yml的配置),如何定義取決于業務需要。
@RestController
@RequestMapping("/test/retry")
public class RetryController {String noete = """@Recover方法必須與@Retryable方法在同一個Spring管理的Bean中,確保AOP代理生效。當存在多個可能的@Recover方法時,Spring按以下優先級選擇:異常類型最具體的方法(如子類異常優先于父類)。返回類型最匹配的方法(避免類型轉換錯誤)。參數列表更匹配的方法(如包含原方法參數)value:拋出指定異常才會重試noRetryFor:指定不處理的異常maxAttempts:最大重試次數,默認3次backoff:重試等待策略,默認使用@Backoff,@Backoff的value(相當于delay)表示隔多少毫秒后重試,默認為1000L;multiplier(指定延遲倍數)默認為0,表示固定暫停1秒后進行重試。""";@Retryable(value = Exception.class, maxAttempts = 3,backoff = @Backoff(delay = 1000,multiplier = 1.5))// name指定的值和我們yml配置保持一致@CircuitBreaker(name = "backendA",fallbackMethod = "fallback")@GetMapping("/test")public String test() {System.out.println("do-something:"+ LocalDateTime.now());long l = System.currentTimeMillis();int a = 0;System.out.println( l % 2 == 0);if (l % 2 == 0) {a = 1 / 0;}System.out.println("res=" + a+"  "+LocalDateTime.now());return "200";}/*** 熔斷器指定的方法* 返回值類型也要一致*/public String fallback(CallNotPermittedException e) {System.out.println("進入熔斷");return "進入了熔斷";}
}

相關源碼:
在這里插入圖片描述
在這里插入圖片描述

  1. @Retryable+@CircuitBreaker 一起使用注意事項:
    Recover 執行順序 > fallbackMethod ;
    如果 @Recover 吞了異常(即沒有手動拋出異常) 是不會再進入fallbackMethod 的,所以很可能造成@Retryable+@CircuitBreaker 一起使用 導致CircuitBreaker失效。如果一定要一起使用,我們可以在Recover把異常拋出去

完整版測試代碼:


@RestController
@RequestMapping("/test/retry")
public class RetryController {String noete = """@Recover方法必須與@Retryable方法在同一個Spring管理的Bean中,確保AOP代理生效。當存在多個可能的@Recover方法時,Spring按以下優先級選擇:異常類型最具體的方法(如子類異常優先于父類)。返回類型最匹配的方法(避免類型轉換錯誤)。參數列表更匹配的方法(如包含原方法參數)value:拋出指定異常才會重試noRetryFor:指定不處理的異常maxAttempts:最大重試次數,默認3次backoff:重試等待策略,默認使用@Backoff,@Backoff的value(相當于delay)表示隔多少毫秒后重試,默認為1000L;multiplier(指定延遲倍數)默認為0,表示固定暫停1秒后進行重試。""";@Retryable(value = Exception.class, maxAttempts = 3,backoff = @Backoff(delay = 1000,multiplier = 1.5))@CircuitBreaker(name = "backendA",fallbackMethod = "fallback")@GetMapping("/test")public String test() {System.out.println("do-something:"+ LocalDateTime.now());long l = System.currentTimeMillis();int a = 0;System.out.println( l % 2 == 0);if (l % 2 == 0) {a = 1 / 0;}System.out.println("res=" + a+"  "+LocalDateTime.now());return "200";}@Retryable(value = Exception.class, maxAttempts = 3,backoff = @Backoff(delay = 1000,multiplier = 1.5))@GetMapping("/test1")public String test1() {System.out.println("do-something:"+ LocalDateTime.now());// NumberFormatExceptionInteger a = Integer.parseInt(null);System.out.println("res=" + a +"  "+LocalDateTime.now());return "200";}@Retryable(value = Exception.class, maxAttempts = 3,backoff = @Backoff(delay = 1000,multiplier = 1.5))@GetMapping("/test2")public String test2(String name) {System.out.println("do-something:"+ LocalDateTime.now());int a = 1 / 0;System.out.println("res=" + a+"  "+LocalDateTime.now());return "200";}/*** @Recover 的返回類型,必須跟 @Retryable修飾的方法返回值一致。*  注意 Recover 執行順序 >  fallbackMethod ; 如果 @Recover 吞了異常(即沒有手動拋出) 是不會再進入fallbackMethod 的*  如果一定要 Recover +  fallbackMethod 同時使用,可以在Recover 把異常拋出去*/@Recoverpublic String recoverTest(ArithmeticException e) {System.out.println("test模擬記錄錯誤日志"+e.getMessage());throw e;
//        return "test降級處理";}@Recoverpublic String recoverTest1(NumberFormatException e) {System.out.println("test1模擬記錄錯誤日志"+e.getMessage());return "test1降級處理";}@Recoverpublic String recoverTest2(ArithmeticException e,String name) {System.out.println("test2模擬記錄錯誤日志"+e.getMessage());return "test2降級處理";}/*** 熔斷器指定的方法* 返回值類型也要一致*/public String fallback(CallNotPermittedException e) {System.out.println("進入熔斷");return "進入了熔斷";}

ratelimiter限流機制

  1. yml配置
    限流和熔斷的配置是類似的:
# resilience4j (輕量級熔斷)
resilience4j:# 限流配置ratelimiter:instances:# 自定義的限流名稱commonRateLimiter:limitForPeriod: 10  # 每個刷新周期內允許的最大請求數limitRefreshPeriod: 1s  # 限流刷新周期timeoutDuration: 100ms  # 獲取許可的等待超時時間registerHealthIndicator: true  # 是否注冊健康指標eventConsumerBufferSize: 100  # 事件緩沖區大小# 熔斷配置      circuitbreaker:instances:# 自定義的熔斷名稱backendA:sliding-window-type: count_based # 默認是count, 還可以配置 TIME_BASED sliding-window-size則表示最近幾秒sliding-window-size: 4 # 只看最近四次調用(為了方便測試)minimum-number-of-calls: 1 #只需一次調用就開始評估failure-rate-threshold: 50 # 失敗率超過50 就開啟熔斷 (開啟熔斷后,后面請求就直接進入熔斷了)wait-duration-in-open-state: 5s # 開啟后5s進入半開狀態  (半開啟是個靈活的狀態,后續服務恢復就不用進入熔斷了)permitted-number-of-calls-in-half-open-state: 2 # 半開狀態允許有兩次測試調用 如果低于 failure-rate-threshold 失敗率 ,則不會進入熔斷automatic-transition-from-open-to-half-open-enabled: true # 半開啟狀態
  1. 代碼中使用,注意限流的補償方法入參需要定義成RequestNotPermitted
  @GetMapping("/limit")@RateLimiter(name = "commonRateLimiter",fallbackMethod = "limit")public String limitTest() {System.out.println("do-something:"+ LocalDateTime.now());int a = 1 / 0;System.out.println("res=" + a+"  "+LocalDateTime.now());return "200";}/*** 注意入參根據業務情況 定義RequestNotPermitted還是Exception * 如果定義成Exception則被@RateLimiter修飾的方法 一旦發生異常就會進入該方法,而不是優先讀取yml的配置* @param e RequestNotPermitted*/public String limit(RequestNotPermitted e) {System.out.println("被限流了");return "被限流了";}
}
  1. 簡單看一下源碼,看看為什么要定義成相關異常
    io.github.resilience4j.ratelimiter.RateLimiter 類:
    下面這行代碼表示被限流了會拋出RequestNotPermitted 異常;
    在這里插入圖片描述
    下面這行則是fallback的一個公用處理,會去找到接收這個異常的方法
    在這里插入圖片描述

tips: 為什么能找到源碼位置? 首先把logging調成debug級別, 找到關鍵輸出的日志對應的類 先打上斷點 再把上下源碼一行一行跟蹤

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85102.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85102.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85102.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

(21)量子計算對密碼學的影響

文章目錄 2??1?? 量子計算對密碼學的影響 &#x1f30c;&#x1f50d; TL;DR&#x1f680; 量子計算&#xff1a;密碼學的終結者&#xff1f;? 量子計算的破壞力 &#x1f510; Java密碼學體系面臨的量子威脅&#x1f525; 受影響最嚴重的Java安全組件 &#x1f6e1;? 后…

經營分析會,財務該怎么做?

目錄 一、業績洞察&#xff1a;從「現象描述」到「因果分析」 1.分層拆解 2.關聯驗證 3.根因追溯 二、預算管理&#xff1a;從「剛性控制」到「動態平衡」 1.分類管控 2.滾動校準 3.價值評估 三、客戶與市場&#xff1a;從「交易記錄」到「價值評估」 1.價值分層 2.…

進階智能體實戰九、圖文需求分析助手(ChatGpt多模態版)(幫你生成 模塊劃分+頁面+表設計、狀態機、工作流、ER模型)

?? 基于 ChatGPT 多模態大模型的需求文檔分析助手 本文將介紹如何利用 OpenAI 的 GPT-4o 多模態能力,構建一個智能的需求文檔分析助手,自動提取功能模塊、菜單設計、字段設計、狀態機、流程圖和 ER 模型等關鍵內容。 一、?? 環境準備 在開始之前,請確保您已經完成了基礎…

圖書管理系統的設計與實現

湖南軟件職業技術大學 本科畢業設計(論文) 設計(論文)題目 圖書管理系統的設計與實現 學生姓名 學生學號 所在學院 專業班級 畢業設計(論文)真實性承諾及聲明 學生對畢業設計(論文)真實性承諾 本人鄭重聲明:所提交的畢業設計(論文)作品是本人在指導教師的指導下,獨…

直線模組在手術機器人中有哪些技術挑戰?

手術機器人在現代醫療領域發揮著越來越重要的作用&#xff0c;直線模組作為其關鍵部件&#xff0c;對手術機器人的性能有著至關重要的影響。然而&#xff0c;在手術機器人中使用直線模組面臨著諸多技術挑戰&#xff0c;具體如下&#xff1a; 1、?高精度要求?&#xff1a;手術…

技術-工程-管用養修保-智能硬件-智能軟件五維黃金序位模型

融智學工程技術體系&#xff1a;五維協同架構 基于鄒曉輝教授的框架&#xff0c;工程技術體系重構為&#xff1a;技術-工程-管用養修保-智能硬件-智能軟件五維黃金序位模型&#xff1a; math \mathbb{E}_{\text{技}} \underbrace{\prod_{\text{Dis}} \text{TechnoCore}}_{\…

InnoDB引擎邏輯存儲結構及架構

簡化理解版 想象 InnoDB 是一個高效運轉的倉庫&#xff1a; 核心內存區 (大腦 & 高速緩存 - 干活超快的地方) 緩沖池 Buffer Pool (最最核心&#xff01;)&#xff1a; 作用&#xff1a; 相當于倉庫的“高頻貨架”。把最常用的數據&#xff08;表數據、索引&#xff09;從…

貧血模型與充血模型:架構設計的分水嶺

在企業級應用的架構設計中&#xff0c;貧血模型和充血模型一直是架構師們爭論的熱點話題。兩者背后分別代表著“事務腳本模式”和“領域模型模式”兩種截然不同的設計思想。而理解這兩者的差異&#xff0c;有助于開發者根據實際業務場景做出更合理的架構決策。 貧血模型&#…

Linux的調試器--gbd/cgbd

1.引入 #include <stdio.h> int Sum(int s, int e) {int result 0;for(int i s; i < e; i){result i;}return result; } int main() {int start 1;int end 100;printf("I will begin\n");int n Sum(start, end);printf("running done, result i…

PPIO × AstrBot:多平臺接入聊天機器人,開啟高效協同 | 教程

在消息平臺接入專屬聊天機器人&#xff0c;能快速生成精準答案&#xff0c;與項目管理、CRM等系統集成后&#xff0c;機器人還能根據任務進展自動建群、推送進度提醒&#xff0c;并精準相關人員&#xff0c;實現信息的高效傳遞。 AstrBot 是一個多平臺聊天機器人及開發框架&…

HAProxy 可觀測性最佳實踐

HAProxy 簡介 HAProxy&#xff08;High Availability Proxy&#xff09;是一款廣泛使用的高性能負載均衡器&#xff0c;支持 TCP 和 HTTP 協議&#xff0c;提供高可用性、負載均衡和代理服務。它特別適用于負載較大的 Web 站點&#xff0c;能夠支持數以萬計的并發連接&#xf…

增強LangChain交互體驗:消息歷史(記憶)功能詳解

背景 在構建聊天機器人時,將對話狀態傳入和傳出鏈至關重要。 LangGraph 實現了內置的持久層,允許鏈狀態自動持久化在內存或外部后端(如 SQLite、Postgres 或 Redis)中。在本文我們將演示如何通過將任意 LangChain runnables 包裝在最小的 LangGraph 應用程序中來添加持久性…

EasyRTC音視頻實時通話助力微信小程序:打造低延遲、高可靠的VoIP端到端呼叫解決方案

一、方案概述? 在數字化通信浪潮下&#xff0c;端到端實時音視頻能力成為剛需。依托龐大用戶生態的微信小程序&#xff0c;是實現此類功能的優質載體。基于WebRTC的EasyRTC音視頻SDK&#xff0c;為小程序VoIP呼叫提供輕量化解決方案&#xff0c;通過技術優化實現低延遲通信&a…

WebVm:無需安裝,一款可以在瀏覽器運行的 Linux 來了

WebVM 是一款可以在瀏覽器中運行的Linux虛擬機。不是那種HTMLJavaScript模擬的UI&#xff0c;完全通過HTML5/WebAssembly技術實現客戶端運行。通過集成CheerpX虛擬化引擎&#xff0c;可直接在瀏覽器中運行未經修改的Debian系統。 Stars 數13054Forks 數2398 主要特點 完整 Lin…

CesiumInstancedMesh 實例

CesiumInstancedMesh 實例 import * as Cesium from cesium;// Three.js 風格的 InstancedMesh 類, https://threejs.org/docs/#api/en/objects/InstancedMesh export class CesiumInstancedMesh {/*** Creates an instance of InstancedMesh.** param {Cesium.Geometry} geom…

創建型模式之Abstract Factory(抽象工廠)

創建型模式之Abstract Factory&#xff08;抽象工廠&#xff09; 摘要&#xff1a; 本文介紹了抽象工廠模式&#xff08;Abstract Factory&#xff09;&#xff0c;它是一種創建型設計模式&#xff0c;提供了一種創建一系列相關對象的接口而無需指定具體類。文章通過手機工廠示…

多卡訓練核心技術詳解

多卡訓練核心技術詳解 多卡訓練 主要圍繞分布式環境初始化、模型并行化、數據分片和梯度同步展開。下面結合您的代碼,詳細解釋這些核心部分: 并行執行命令 torchrun --nproc_per_node=5 TokenLossMulCard.py 1. 分布式環境初始化 def init_distributed():init_process_…

OpenCV---minAreaRect

一、基本概念與用途 minAreaRect是OpenCV中用于計算點集的最小面積旋轉矩形的函數。在計算機視覺領域&#xff0c;它常被用于&#xff1a; 目標檢測中獲取傾斜對象的邊界框&#xff08;如傾斜的車牌、文本行、工業零件&#xff09;形狀分析與識別&#xff08;如確定物體的主方…

高端裝備制造企業如何選擇適配的項目管理系統提升項目執行效率?附選型案例

高端裝備制造項目通常涉及多專業協同、長周期交付和高風險管控&#xff0c;因此系統需具備全生命周期管理能力。例如&#xff0c;北京奧博思公司出品的 PowerProject 項目管理系統就是一款非常適合制造企業使用的項目管理軟件系統。 國內某大型半導體裝備制造企業與奧博思軟件達…

如何科學測量系統的最高QPS?

要準確測量系統的最高QPS&#xff08;Queries Per Second&#xff09;&#xff0c;既不能簡單依賴固定請求數&#xff08;如2萬次&#xff09;&#xff0c;也不能盲目壓到服務器崩潰。以下是專業的方法論和步驟&#xff1a; 1. 核心原則 目標&#xff1a;找到系統在穩定運行&a…