Spring Retry 异常重试机制:从入门到生产实践
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