重学SpringBoot3-Spring Retry实践

06-01 1353阅读

更多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 项目中添加必要的依赖:

              org.springframework.retry
              spring-retry
              2.0.5
          
          
              org.springframework
              spring-aspects
              6.1.13
          
          

          在启动类或配置类上添加 @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);
              }
          

          重试和失败恢复效果

          重学SpringBoot3-Spring Retry实践

          注意事项

          注意@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  void onError(RetryContext context, 
                        RetryCallback callback, Throwable throwable) {
                    // 记录错误日志
                    log.error("Retry error occurred", throwable);
                }
                
                @Override
                public  void close(RetryContext context,
                        RetryCallback 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;
                }
            }
            

            监听重试效果

            重学SpringBoot3-Spring Retry实践

            4. 最佳实践

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

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

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

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

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

            5. 总结

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

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

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码