springboot重试组件

本文介绍如何使用Spring AOP实现一个可配置的重试机制,通过自定义注解和切点,使得业务代码可以轻松地添加重试逻辑,支持特定异常类型的重试。

最近有一个业务需要有重试机制,感觉应该写一个能够重试的组件。

 

首先创建一个注解

/**
 * @Author GUOSHAOHUA093
 * @Description 重试拦截
 * @Date 9:14 2018/12/8
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface IsTryAgain {
    int times() default 1;
    Class<? extends Exception> exception() default Exception.class;

} 

在常见一个切入点

/**
 *@Author GUOSHAOHUA093
 *@Description 重试切点
 *@Date 14:07 2018/12/8
 */
@Component  //声明组件
@Aspect
public class TryAgainPointcut {
	
	@Pointcut("execution(* com.pingan.medical.service..*(..))")
	public void businessService() {
	}
	
}

因为我们希望每次重试都是一个新的事务,所以我们需要高于事务去执行,并且我们项根据传入的Exception自行来判断对什么样的异常进行重试(目前只支持放入一种哈,后续看心情开发中。。。。)。

/**
 *@Author GUOSHAOHUA093
 *@Description 重试拦截处理方法
 *@Date 14:09 2018/12/8
 */
@Component  //声明组件
@Aspect
class RetryAgainExecutor implements Ordered {

   private static final Logger logger = LoggerFactory.getLogger(RetryAgainExecutor.class);
   
   private static final int DEFAULT_MAX_RETRIES = 2;

   private int maxRetries = DEFAULT_MAX_RETRIES;
   private int order = 2;

   public void setMaxRetries(int maxRetries) {
      this.maxRetries = maxRetries;
   }
   
   public int getOrder() {
      return this.order;
   }
   
   @Around("@annotation(com.pingan.medical.config.interceptor.tryAgain.IsTryAgain)")
   public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
      //得到重试次数
      MethodSignature signature = (MethodSignature) pjp.getSignature();
      Method method = signature.getMethod();
      IsTryAgain isTryAgain = method.getAnnotation(IsTryAgain.class);
      int maxTimes = isTryAgain.times();
      int numAttempts = 0;
      Exception retryException;
      do {
         numAttempts++;
         try {
            logger.info("这是第"+numAttempts+"次访问");
            return pjp.proceed();
         }catch(Exception ex) {
            if (isTryAgain.exception().isInstance(Object.class) || isTryAgain.exception().isInstance(ex)) {
               retryException = ex;
            } else {
               throw ex;
            }

         }
      }while(numAttempts < maxTimes);

      
      throw retryException;
   }

}

 用的时候就很方便啦,写了exception就会对指定的exception做拦截,不写就会对所有的exception进行拦截。

@IsTryAgain(times = 2,exception = CustomException.class)
@Transactional
public ApiResult test() throw CustomException(){

注意事项,如果用到事务,一定要让拦截器高于事务执行。

至此就结束了。

<think>嗯,用户想解决Spring Boot中Feign调用失败时的重试问题,需要配置重试机制。我应该从哪些方面入手呢? 首先,我记得Feign本身不直接提供重试功能,而是依赖底层的HTTP客户端,比如默认的HttpURLConnection或者集成Ribbon时的配置。不过现在可能更多是使用Spring Cloud OpenFeign,结合LoadBalancer或其他组件。需要确认用户使用的Spring Cloud版本,因为不同版本的配置可能不同。 用户需要的是配置重试的教程和示例。首先应该指导添加Feign的依赖,确保项目中有spring-cloud-starter-openfeign。然后,可能需要在配置文件中设置相关的重试参数,比如最大尝试次数、重试间隔等。另外,可能需要自定义Retryer或者使用@Configuration类来覆盖默认设置。 记得Feign的重试机制和Ribbon的重试配置有关,特别是在旧版本中。如果用户用的是新版本的Spring Cloud,可能已经移除了Ribbon,改用Spring Cloud LoadBalancer,这时候配置方式可能不同。需要查一下最新的文档,或者参考现有的配置方法。 另外,超时设置也很重要,比如connectTimeout和readTimeout,这些可能影响重试的行为。需要提醒用户正确设置这些参数,避免因超时导致的重试失败。 还有,可能需要自定义Retryer实现,比如实现Retryer接口,并注入到Feign的配置中。这样可以更灵活地控制重试逻辑,比如重试次数、间隔时间等。例如,使用Retryer.Default或者自定义的指数退避策略。 此外,异常处理也是关键。Feign默认只会对某些异常进行重试,比如IOException或者FeignException,可能需要检查哪些异常会触发重试,或者是否需要自定义ErrorDecoder来处理特定的错误响应,从而决定是否重试。 还要注意,开启日志有助于调试,可以配置Feign的日志级别来查看重试的情况,确认配置是否生效。 最后,提供示例代码很重要,比如在配置类中定义Retryer的Bean,或者在application.yml中设置相关属性。同时,提醒用户不同的Spring Cloud版本可能有不同的配置方式,需要根据实际情况调整。 可能还需要引用用户提供的引用内容,比如启动类需要@EnableFeignClients注解,配置类中使用@Bean来覆盖默认设置。例如引用中的[^1]、[^2]、[^3]提到了启动类的注解,而[^4]提到了添加依赖,[^5]提到了配置覆盖。这些可以作为参考,整合到回答中。 总结步骤应该是:添加依赖、配置参数(如重试次数、超时时间)、自定义Retryer、处理异常、开启日志。同时,给出示例代码,包括配置文件和Java配置类,并解释各部分的作用。还要注意版本差异和常见问题,比如重试不生效的可能原因,如未正确配置或依赖缺失。</think>### Spring Boot Feign Client 失败重试机制配置教程 #### 1. 添加Feign依赖 首先确保`pom.xml`中已包含Spring Cloud OpenFeign依赖(Spring Cloud 2020.0.0及以上版本需使用`spring-cloud-starter-openfeign`): ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> ``` #### 2. 启用Feign客户端 在启动类添加`@EnableFeignClients`注解: ```java @SpringBootApplication @EnableFeignClients public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } } ``` [^3] #### 3. 配置重试机制 ##### 方式一:通过配置文件 在`application.yml`中设置重试参数(需配合`spring-cloud-starter-loadbalancer`): ```yaml spring: cloud: loadbalancer: retry: enabled: true feign: client: config: default: connectTimeout: 5000 # 连接超时时间(毫秒) readTimeout: 5000 # 读取超时时间 loggerLevel: basic # 开启日志 retryer: feign.Retryer.Default ``` ##### 方式二:自定义Retryer 创建配置类实现自定义重试策略: ```java @Configuration public class FeignConfig { @Bean public Retryer feignRetryer() { // 参数说明:重试间隔(ms), 最大间隔(ms), 最大尝试次数(包含首次调用) return new Retryer.Default(100, 1000, 3); } } ``` #### 4. 异常处理增强 实现`ErrorDecoder`处理特定异常: ```java public class FeignErrorDecoder implements ErrorDecoder { @Override public Exception decode(String methodKey, Response response) { if (response.status() >= 500) { return new RetryableException(...); // 触发重试 } return new RuntimeException("Non-retryable error"); } } ``` #### 5. 验证重试行为 通过日志观察重试次数: ```log [MyFeignClient#getData] ---> GET http://service-url/data [MyFeignClient#getData] <--- ERROR 500 (123ms) [MyFeignClient#getData] Retry attempt 1 (of 3) ``` #### 注意事项 1. 重试仅对`IOException`和`RetryableException`生效 2. 幂等操作建议重试(GET/HEAD),非幂等操作慎用 3. 超时设置需大于服务实际响应时间 4. 新版Spring Cloud中需排除Ribbon依赖(若存在)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值