版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/Phone_1070333541/article/details/85010531 一、依赖导入。 <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> 1 2 3 4 二、service层如下。 import com.hteamtech.callback.common.RetMessage; import org.springframework.retry.RetryException; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.EnableRetry; import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat; import java.util.Date;
/** * @描述 * @创建人 梁XL * @创建时间 2018/12/13 */ @Service @EnableRetry public class TestRetryService {
private static final String RES_SUCCESS = "success"; private static final long TIME_UNIT = 1000 * 60; private static final int MAX_ATTEMPTS = 5;
@Retryable(value = {RetryException.class, RuntimeException.class}, maxAttempts = MAX_ATTEMPTS, backoff = @Backoff(delay = TIME_UNIT, maxDelay = TIME_UNIT * 6, multiplier = 2)) public void testRetry(RetMessage msg) { // 调用商户的接口 String result = showMsg();
// 打印时间 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String format = simpleDateFormat.format(new Date()); System.out.println("第" + msg.getTimes() + "次异步回调,时间为" + format + ",返回结果为" + result);
// 抛出重试的异常 if (!RES_SUCCESS.equals(result)) { msg.setTimes(msg.getTimes() + 1); msg.setSuccess(false); throw new RetryException("retry failed"); } else { msg.setSuccess(true); }
}
public String showMsg() { return "false"; }
@Recover public void recover(RemoteAccessException e) { logger.info(e.getMessage()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 三、运行打印结果。 第1次异步回调,时间为2018-12-14 14:44:35,返回结果为false 第2次异步回调,时间为2018-12-14 14:45:35,返回结果为false 第3次异步回调,时间为2018-12-14 14:47:35,返回结果为false 第4次异步回调,时间为2018-12-14 14:51:35,返回结果为false 第5次异步回调,时间为2018-12-14 14:57:35,返回结果为false
// 之后便抛出ReTry异常 1 2 3 4 5 6 7 四、注解解析 @Retryable
被注解的方法发生异常时会重试 value:指定发生的异常进行重试 include:和value一样,默认空,当exclude也为空时,所有异常都重试 exclude:指定异常不重试,默认空,当include也为空时,所有异常都重试 maxAttemps:重试次数,默认3 backoff:重试补偿机制,默认没有 @Backoff
延迟策略 delay:指定延迟后重试 multiplier:指定延迟的倍数,比如delay=5000l,multiplier=2时,第一次重试为5秒后,第二次为10秒,第三次为20秒 @Recover
当重试到达指定次数时,被注解的方法将被回调,可以在该方法中进行日志处理。需要注意的是发生的异常和入参类型一致时才会回调。 五、避坑指南。 使用了@Retryable的方法不能再本类内被调用,不然重试机制不会生效。也就是要标记为@Service,然后再其他类使用@Autowired 注入或者@Bean去实例化才能生效。 要触发@Recover方法,那么在@Retryable方法上不能有返回值,只能是void才能生效。 使用了@Retryable的方法里面不能使用try…catch包裹,要抛出异常,不然不会触发。 在重试期间这个方法是同步的,如果使用类似Spring Cloud这种框架的熔断机制时,可以结合重试机制来重试后返回结果。 SpringRetry不只能注入方式去实现,还可以通过API的方式实现,类似熔断处理的机制就基于API方式实现会比较宽松。 ———————————————— 版权声明:本文为博主「_半年」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/Phone_1070333541/article/details/85010531