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的直接返回原生对象

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
普通 Spring 项目Spring Boot 项目集成,可以通过以下步骤实现: 1. 在 Spring Boot 项目中引入普通 Spring 项目的依赖。可以使用 Maven 或 Gradle 等构建工具,在 Spring Boot 项目的 pom.xml 或 build.gradle 文件中添加普通 Spring 项目的依赖,例如: ``` <dependency> <groupId>com.example</groupId> <artifactId>my-spring-project</artifactId> <version>1.0.0</version> </dependency> ``` 2. 在 Spring Boot 项目的启动类中,使用 @ImportResource 注解导入普通 Spring 项目的配置文件,例如: ``` @SpringBootApplication @ImportResource("classpath:applicationContext.xml") public class MySpringBootApplication { public static void main(String[] args) { SpringApplication.run(MySpringBootApplication.class, args); } } ``` 这里的 "classpath:applicationContext.xml" 是普通 Spring 项目的配置文件路径,可以根据实际情况进行修改。 3. 在普通 Spring 项目中,需要将一些配置从 XML 配置文件中移动到 Java 配置类中,以便与 Spring Boot 项目集成。可以使用 @Configuration 注解定义 Java 配置类,例如: ``` @Configuration public class MyConfiguration { @Bean public MyService myService() { return new MyServiceImpl(); } } ``` 然后在 Spring Boot 项目的启动类中,使用 @Import 注解导入 Java 配置类,例如: ``` @SpringBootApplication @Import({MyConfiguration.class}) public class MySpringBootApplication { public static void main(String[] args) { SpringApplication.run(MySpringBootApplication.class, args); } } ``` 这样就可以在 Spring Boot 项目中使用普通 Spring 项目中定义的 bean 了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值