SpringBoot项目集成SpringRetry进行接口重试

为什么要做接口重试?

业务系统服务调用第三方系统的接口,以及第三方系统调用业务系统的服务时,当出现网络异常或超时导致的失败,需要进行重试,确保接口的可靠性

重试机制:

  • 不允许重试:只允许调用重试回调一次
  • 不限次数重试:允许无限重试,直到成功,此方式逻辑不当会导致死循环
  • 固定次数重试:默认重试最大次数为3次,默认使用的策略
  • 超时时间重试策略:默认超时时间为1秒,在指定的超时时间内允许重试
  • 异常重试:针对不同异常的设置不同的重试策略,类似组合重试策略

最佳实践–SpringRetry

  • 添加依赖
		<dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
        </dependency>
  • 启动类添加注解(@EnableRetry),开启重试机制

  • 新增重试类

@Service
public class RetryServiceImpl {

    private static Logger logger = LoggerFactory.getLogger(RetryServiceImpl.class);

    private static RestTemplate restTemplate;

    @Autowired
    public RetryServiceImpl(RestTemplate restTemplate) {
        RetryServiceImpl.restTemplate = restTemplate;
    }

    @Retryable(value = {ConnectTimeoutException.class, ResourceAccessException.class},maxAttempts = 3,backoff = @Backoff(delay = 2000))
    public String doPostJsonNotToken(String url, String json) {
        String resultString = "";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("application/json; charset=UTF-8"));
        HttpEntity<String> formEntity = new HttpEntity<>(json, headers);
        resultString = restTemplate.postForObject(url, formEntity, String.class);
        String logInfo = String.format("调用接口:%s,参数:%s,返回结果%s",url, JSON.toJSONString(json),resultString);
        logger.info(logInfo);
        return resultString;
    }

    @Recover
    public String recoverConnect(ConnectTimeoutException e) {
        logger.error("重试机制3次已完成,依然连接超时..",e);
        return "";
    }

    @Recover
    public String recoverRead(ResourceAccessException e) {
        logger.error("重试机制3次已完成,依然读取超时..",e);
        return "";
    }
}

在这里插入图片描述
当其他地方调用这个接口,发生网络抖动、读取资源超时,会自动重试三次.

@Retryable(value = {ConnectTimeoutException.class, ResourceAccessException.class},maxAttempts = 3,backoff = @Backoff(delay = 2000))

说一说上面的两个异常ConnectTimeoutException、ResourceAccessException 分别是连接异常和读取资源超时异常.分别对应RestTemplate设置的连接时间和读取资源时间,当超时是会报对应的异常.

@Configuration
public class RestTemplateConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(10000);
        factory.setReadTimeout(100000);
        RestTemplate restTemplate = new RestTemplate(factory);
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        // 使用 utf-8 编码集的 conver 替换默认的 conver
        // (默认的 string conver 的编码集为"ISO-8859-1")
        messageConverters.removeIf(converter -> converter instanceof StringHttpMessageConverter);
        messageConverters.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }
}

注意:

如果你发现你的接口出现对应的异常,没有去重试时,需要注意Retryable方法只有直接通过代理对象调用时才会生效,通过其他方法间接调用不生效(所有基于AOP的注解都一样),工具类调用是不可以的.

温馨提示:在Spring中,只有需要用到Aop代理的类才会生成代理对象,不需要Aop的直接返回原生对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值