当前位置: 首页 > article >正文

重学SpringBoot3-Spring Retry实践

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》
期待您的点赞👍收藏⭐评论✍

重学SpringBoot3-Spring Retry实践

  • 1. 简介
  • 2. 环境准备
  • 3. 使用方式
    • 3.1 注解方式
      • 基础使用
      • 自定义重试策略
      • 失败恢复机制
      • 重试和失败恢复效果
      • 注意事项
    • 3.2 编程式使用
    • 3.3 监听重试过程
      • 监听重试效果
  • 4. 最佳实践
  • 5. 总结

1. 简介

Spring Retry是Spring生态系统中的一个重要组件,它提供了自动重试失败操作的能力。在分布式系统中,由于网络抖动、服务暂时不可用等临时性故障,重试机制显得尤为重要。本文将详细介绍如何在 SpringBoot 3 应用中集成和使用 Spring Retry。

2. 环境准备

首先在 SpringBoot 3 项目中添加必要的依赖:

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>2.0.5</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>6.1.13</version>
</dependency>

在启动类或配置类上添加 @EnableRetry 注解以启用重试功能:

@SpringBootApplication
@EnableRetry
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

3. 使用方式

3.1 注解方式

基础使用

最简单的使用方式是通过 @Retryable 注解:

@Service
public class UserService {
    
    @Retryable
    public void riskyOperation() {
        // 可能失败的操作
    }
}

自定义重试策略

可以通过 @Retryable 注解的参数来自定义重试行为:

@Service
@Slf4j
public class EmailServiceImpl implements IEmailService {

    @Resource
    private JavaMailSender mailSender;

    @Value("${spring.mail.username}")
    private String from;

    /**
     * 发送简单文本邮件
     *
     * @param to
     * @param subject
     * @param text
     */
    @Override
    @Retryable(retryFor = MailSendException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000))
    public void sendSimpleEmail(String to, String subject, String text) {
        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom(from);
            message.setTo(to);
            message.setSubject(subject);
            message.setText(text);
            mailSender.send(message);
            log.info("Simple email sent successfully to: {}", to);
        } catch (Exception e) {
            log.error("Failed to send simple email", e);
            throw new MailSendException("Failed to send email", e);
        }
    }
}

当执行发生指定异常,将会尝试进行重试,一旦达到最大尝试次数,但仍有异常发生,就会抛出 ExhaustedRetryException。重试最多可进行三次,两次重试之间的延迟时间默认为一秒。

失败恢复机制

使用 @Recover 注解定义重试失败后的恢复方法:

    /**
     * 发送简单文本邮件
     *
     * @param to
     * @param subject
     * @param text
     */
    @Override
    @Retryable(retryFor = MailSendException.class, // 指定异常类型
            maxAttempts = 3, // 最大重试次数
            backoff = @Backoff(delay = 1000) // 指定退避策略,例如延迟时间
    )
    public void sendSimpleEmail(String to, String subject, String text) {
        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom(from);
            message.setTo(to);
            message.setSubject(subject);
            message.setText(text);
            mailSender.send(message);
            log.info("Simple email sent successfully to: {}", to);
        } catch (Exception e) {
            log.error("Failed to send simple email", e.getMessage());
            throw new MailSendException("Failed to send email", e);
        }
    }

    @Recover
    public void recover(MailSendException e, String param) {
        // 处理最终失败的情况
        log.error("Final recovery : {}", param);
    }

重试和失败恢复效果

重试和失败恢复效果

注意事项

注意@Recover 失效的情况:

  • @Recover 方法的参数类型与实际异常不匹配;
  • @Recover 方法的返回类型与 @Retryable 方法不一致;
  • @Recover 方法的其他参数与 @Retryable 方法参数不匹配。

3.2 编程式使用

除了注解方式,Spring Retry 还提供了 RetryTemplate 用于编程式重试:

@Configuration
public class RetryConfig {
    
    @Bean
    public RetryTemplate retryTemplate() {
        RetryTemplate template = new RetryTemplate();
        
        // 配置重试策略
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        retryPolicy.setMaxAttempts(3);
        
        // 配置退避策略
        FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
        backOffPolicy.setBackOffPeriod(1000L);
        
        template.setRetryPolicy(retryPolicy);
        template.setBackOffPolicy(backOffPolicy);
        
        return template;
    }
}

使用RetryTemplate:

@Service
public class UserService {
    
    @Autowired
    private RetryTemplate retryTemplate;
    
    public void executeWithRetry() {
        retryTemplate.execute(context -> {
            // 需要重试的业务逻辑
            return null;
        });
    }
}

3.3 监听重试过程

通过实现RetryListener接口,可以监听重试的整个生命周期:

public class CustomRetryListener extends RetryListenerSupport {
    
    @Override
    public <T, E extends Throwable> void onError(RetryContext context, 
            RetryCallback<T, E> callback, Throwable throwable) {
        // 记录错误日志
        log.error("Retry error occurred", throwable);
    }
    
    @Override
    public <T, E extends Throwable> void close(RetryContext context,
            RetryCallback<T, E> callback, Throwable throwable) {
        // 重试结束时的处理
        log.info("Retry completed");
    }
}

将监听器注册到RetryTemplate:

@Configuration
public class RetryConfig {
    
    @Bean
    public RetryTemplate retryTemplate() {
        RetryTemplate template = new RetryTemplate();
        // ... 其他配置 ...
        template.registerListener(new CustomRetryListener());
        return template;
    }
}

监听重试效果

监听重试过程

4. 最佳实践

  1. 明确重试场景:只对临时性故障使用重试机制,对于业务错误或永久性故障应直接失败。

  2. 设置合理的重试次数:通常3-5次即可,过多的重试可能会加重系统负担。

  3. 使用退避策略:建议使用指数退避策略(ExponentialBackOffPolicy),避免立即重试对系统造成冲击。

  4. 添加监控和日志:通过RetryListener记录重试情况,便于问题排查。

  5. 设置超时时间:避免重试过程持续时间过长。

5. 总结

Spring Retry为Spring应用提供了强大而灵活的重试机制,既可以通过注解优雅地实现重试,也可以使用RetryTemplate进行更细粒度的控制。在实际应用中,合理使用重试机制可以提高系统的健壮性和可用性。

需要注意的是,重试机制并非万能药,在使用时要根据具体场景选择合适的重试策略,并做好监控和告警,以便及时发现和处理问题。


http://www.kler.cn/a/406216.html

相关文章:

  • 使用 Maven 构建一个简单的 Java 项目
  • node.js fluent-ffmpeg 桌面推流
  • Android-如何实现Apng动画播放
  • 卷积神经网络各层介绍
  • 【代码pycharm】动手学深度学习v2-04 数据操作 + 数据预处理
  • Spring Boot + Vue 基于 RSA 的用户身份认证加密机制实现
  • 哈希表(极速学习版)
  • Oracle 到 Elasticsearch 数据迁移同步
  • 深入探索:C++红黑树原理与实现
  • 16. 整数n内含有数字2的小游戏
  • 043 商品详情
  • Rust学习(八):异常处理和宏编程:
  • linux 网络安全不完全笔记
  • 时间序列在数据embedding方面有哪些创新方法和工作?
  • Web3和区块链如何促进数据透明与隐私保护的平衡
  • 设计模式之 外观模式
  • Fakelocation Server服务器/专业版 ubuntu
  • [Unity]TileMap开发,TileMap地图缝隙问题
  • 打造网页版Ubuntu环境:群晖NAS部署docker-webtop与远程访问指南
  • Linux高阶——1118—TCP客户端服务端
  • 前端速通(HTML)
  • 气象指数推进光伏“靠天吃饭”?
  • 【设计模式】【创建型模式(Creational Patterns)】之工厂方法模式
  • Utf8Json 枚举序列化为整型(默认string)
  • 《剖析 Spring 原理:深入源码的旅程(一)》
  • ⭐️ GitHub Star 数量前十的工作流项目