@Retryable
?注解簡介
@Retryable
?注解是 Spring Retry 模塊提供的,用于自動重試可能會失敗的方法。在微服務架構和分布式系統中,服務之間的調用可能會因為網絡問題、服務繁忙等原因失敗。使用?@Retryable
?可以提高應用的穩定性和容錯能力?1。
使用步驟
(1)添加依賴
首先,確保你的 Spring Boot 項目中包含了?spring-retry
?依賴。如果使用 Maven,可以在?pom.xml
?文件中添加以下依賴:
<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId>
</dependency>
(2)啟用重試
在 Spring Boot 應用的主類或配置類上添加?@EnableRetry
?注解,啟用重試功能?16。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;@SpringBootApplication
@EnableRetry
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}
(3)使用?@Retryable
?注解
在需要進行重試的方法上添加?@Retryable
?注解。
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;@Service
public class MyService {@Retryable(value = {MyNetworkException.class}, maxAttempts = 3)public String fetchDataFromRemote() {System.out.println("嘗試調用遠程服務...");// 模擬可能失敗的遠程調用if (Math.random() < 0.5) {throw new MyNetworkException("網絡異常");}return "調用成功";}
}
在這個例子中,fetchDataFromRemote
?方法在拋出?MyNetworkException
?異常時會進行重試,最多重試 3 次。
@Retryable
?注解的屬性
@Retryable
?注解提供了多個屬性,用于配置重試策略?1。
-
value
?/?exception
指定需要重試的異常類型。可以指定一個或多個異常類。
@Retryable(value = {MyNetworkException.class, TimeoutException.class}) public String fetchDataFromRemote() {// ... }
-
maxAttempts
指定最大重試次數,包括第一次調用。默認值為 3。
@Retryable(value = MyNetworkException.class, maxAttempts = 5) public String fetchDataFromRemote() {// ... }
-
backoff
指定重試之間的退避策略。可以使用?
@Backoff
?注解配置退避策略。delay
:重試之間的延遲時間,單位為毫秒。multiplier
:延遲倍數,用于實現指數退避。random
:是否在延遲時間上增加一個隨機值,以避免多個服務同時重試。
import org.springframework.retry.annotation.Backoff;@Retryable(value = MyNetworkException.class, backoff = @Backoff(delay = 2000, multiplier = 1.5)) public String fetchDataFromRemote() {// ... }
在這個例子中,第一次重試延遲 2 秒,第二次重試延遲 3 秒 (2 * 1.5),以此類推。
@Recover
?注解
@Recover
?注解用于指定重試失敗后的恢復方法。恢復方法的參數必須與重試方法拋出的異常類型相匹配,并且必須在同一個類中。
import org.springframework.retry.annotation.Recover;@Service
public class MyService {@Retryable(value = {MyNetworkException.class}, maxAttempts = 3)public String fetchDataFromRemote() {System.out.println("嘗試調用遠程服務...");// 模擬可能失敗的遠程調用if (Math.random() < 0.5) {throw new MyNetworkException("網絡異常");}return "調用成功";}@Recoverpublic String recover(MyNetworkException e) {System.out.println("重試失敗,執行恢復邏輯...");// 處理異常的邏輯,例如返回默認值或記錄日志return "默認值";}
}
在這個例子中,如果?fetchDataFromRemote
?方法重試 3 次后仍然失敗,會調用?recover
?方法處理?MyNetworkException
?異常。
-
第一個參數必須是?
Throwable
?類型或其子類型:@Recover
?方法的第一個參數必須是?Throwable
?類型,或者?@Retryable
?方法中聲明的異常類型(或其父類)。- 這個參數用于接收?
@Retryable
?方法拋出的異常。
-
后續參數必須與?
@Retryable
?方法的參數類型和順序一致:@Recover
?方法的后續參數必須與對應的?@Retryable
?方法的參數類型和順序完全一致。- 這些參數用于將?
@Retryable
?方法的參數傳遞給?@Recover
?方法。
-
參數數量:
@Recover
?方法的參數數量必須等于?@Retryable
?方法的參數數量加 1(用于接收異常)。
當被?
@Retryable
?注解的方法經過多次重試都失敗,并且成功調用了?@Recover
?注解的恢復方法后,最初調用?@Retryable
?方法的方法會拿到?@Recover
?方法的返回值。
- 初始調用:?外部方法調用被?
@Retryable
?注解的方法。- 重試失敗:?
@Retryable
?方法執行失敗,并且經過配置的重試次數后仍然失敗。- 調用?
@Recover
:?Spring Retry 框架會自動查找并調用與?@Retryable
?方法簽名匹配的?@Recover
?方法。- 返回結果:?
@Recover
?方法執行完畢后,會將它的返回值返回給最初調用?@Retryable
?方法的外部方法。關鍵點:
@Recover
?方法的返回值類型必須與?@Retryable
?方法的返回值類型相同,這樣才能保證類型安全。- 如果?
@Recover
?方法本身也拋出了異常,那么這個異常會直接拋給最初的調用者,不會再進行重試。如果你沒有定義?
@Recover
?注解的方法,并且?@Retryable
?注解的方法在經過所有重試次數后仍然失敗,那么最初調用?@Retryable
?方法的地方會拋出?RetryException
?異常。具體流程如下:
- 初始調用:?外部方法調用被?
@Retryable
?注解的方法。- 重試失敗:?
@Retryable
?方法執行失敗,并且經過配置的重試次數后仍然失敗。- 沒有?
@Recover
?方法:?Spring Retry 框架找不到與?@Retryable
?方法簽名匹配的?@Recover
?方法。- 拋出?
RetryException
:?Spring Retry 框架會拋出一個?RetryException
?異常,該異常會傳遞給最初調用?@Retryable
?方法的外部方法。