Spring Retry 異常重試機制:從入門到生產實踐
適用版本:Spring Boot 3.x + spring-retry 2.x
本文覆蓋 注解聲明式、RetryTemplate 編程式、監聽器、最佳實踐 與 避坑清單,可直接落地生產。
一、核心坐標
<!-- Spring Boot Starter 已經幫你管理版本 -->
<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId>
</dependency>
<!-- AOP 支持 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
二、開啟重試能力
在啟動類或任意 @Configuration
上添加:
@SpringBootApplication
@EnableRetry // <-- 只需這一行
public class Application { }
三、注解式:最常用 80% 場景
3.1 基本用法
@Service
public class OrderService {@Retryable(retryFor = ConnectException.class, // 觸發重試的異常maxAttempts = 3, // 含首次,共 3 次backoff = @Backoff(delay = 1000, // 首次延遲 1smultiplier = 1.5 // 指數退避 1→1.5→2.25s))public void pay(int orderId) throws ConnectException {// 模擬遠程調用throw new ConnectException("網絡抖動");}
}
3.2 兜底恢復
@Recover
public void payRecover(ConnectException e, int orderId) {log.error("訂單 {} 支付失敗,進入補償流程", orderId);// 發消息、記錄表、人工審核...
}
注意:
@Recover
方法簽名必須與@Retryable
一致(異常類型 + 參數 + 返回值),否則不生效 。
四、編程式:RetryTemplate 細粒度控制
適用于 動態策略 或 無 Spring Bean 場景。
@Configuration
public class RetryConfig {@Beanpublic RetryTemplate retryTemplate() {return RetryTemplate.builder().maxAttempts(5).exponentialBackoff(1000, 1.5, 10000) // 初始 1s、乘 1.5、最大 10s.retryOn(ConnectException.class).build();}
}@Service
public class ReportService {@Autowiredprivate RetryTemplate retryTemplate;public String generate() {return retryTemplate.execute(ctx -> {// 模板內部自動重試return remoteClient.generate();});}
}
五、監聽重試生命周期
實現 RetryListener
可以 記錄指標 / 報警 / 鏈路追蹤。
@Component
public class RetryLogger implements RetryListener {@Overridepublic <T, E extends Throwable> void onError(RetryContext ctx,RetryCallback<T, E> callback,Throwable throwable) {log.warn("第 {} 次重試失敗: {}", ctx.getRetryCount(), throwable.getMessage());}
}
注冊到模板:
retryTemplate.registerListener(new RetryLogger());
六、生產級最佳實踐
維度 | 建議 |
---|---|
重試場景 | 僅對 網絡、鎖、瞬時故障;業務校驗失敗不重試 |
次數 & 退避 | 3~5 次 + 指數退避,避免雪崩 |
冪等性 | 寫操作需保證 冪等鍵 / 去重表 |
超時控制 | 方法級別設置 timeout ,防止長時間阻塞 |
監控告警 | 通過 Micrometer + RetryListener 導出 重試次數、成功率 |
七、常見踩坑清單
癥狀 | 原因 | 解決 |
---|---|---|
重試不觸發 | 直接 new 調用 / 異常被吃掉 | 必須走 Spring 代理拋出異常 |
@Recover 不執行 | 簽名不一致 | 保持異常類型、參數、返回值一致 |
無限重試 | maxAttempts = Integer.MAX_VALUE | 顯式設置合理上限 |
線程阻塞 | 退避策略未設 maxDelay | 設置最大等待時間 |
八、小結一句話
Spring Retry 通過 注解 + AOP 或 RetryTemplate 提供聲明式/編程式重試,在 可觀測、可配置、無侵入 的前提下極大提升了分布式系統的健壯性;
牢記“次數、退避、冪等、監控”四要素,即可安全落地生產。
完整示例代碼已上傳 GitHub:
https://github.com/your-org/spring-retry-demo