Springboot如何实现接口重试

一、前言
在实际项目中,往往在某些特定的场景下,我们需要实现接口调用异常的重试机制,比如在跨平台的业务中,需要调用第三方接口实现某些功能,难免会遇到一些网络问题,这时候需要加入重试机制了。

二、如何实现?
第一种:基于spring retry实现的重试。
1.引入maven依赖

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

2.编写重试配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;

@Configuration
@EnableRetry
public class RetryConfig {
    @Bean
    public RetryTemplate retryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();
        // 设置重试策略
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        // 最大重试次数
        retryPolicy.setMaxAttempts(3); 
        retryTemplate.setRetryPolicy(retryPolicy);
        // 设置重试间隔
        FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
        // 重试间隔(毫秒)
        backOffPolicy.setBackOffPeriod(1000); 
        retryTemplate.setBackOffPolicy(backOffPolicy);
        return retryTemplate;
    }
}

3.定义一个服务类,编写需要重试的方法

import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

@Service
public class RetryService {
    @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000))
    public void callApiMethod() {
        // 这里编写调用外部API的代码
        // 如果调用失败会自动重试,最多重试3次,间隔1秒
    }
}

4.可以配置重试监听器
如果想在重试发生时执行特定操作,可以添加一个实现了RetryListener接口的监听器类,并在RetryTemplate中设置该监听器。

import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.listener.RetryListenerSupport;
import org.springframework.stereotype.Component;

@Component
public class MyRetryListener extends RetryListenerSupport {
    @Override
    public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
        System.out.println("重试发生,异常信息为:" + throwable.getMessage());
        // 在这里可以记录日志或执行其他操作
        super.onError(context, callback, throwable);
    }
}

接着在RetryTemplate中注册这个监听器。

@Configuration
@EnableRetry
public class RetryConfig {

    @Autowired
    private MyRetryListener myRetryListener;

    @Bean
    public RetryTemplate retryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();
        RetryTemplate retryTemplate = new RetryTemplate();
        // 设置重试策略
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        // 最大重试次数
        retryPolicy.setMaxAttempts(3); 
        retryTemplate.setRetryPolicy(retryPolicy);
        // 设置重试间隔
        FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
        // 重试间隔(毫秒)
        backOffPolicy.setBackOffPeriod(1000); 
        retryTemplate.setBackOffPolicy(backOffPolicy);
        // 注册重试监听器
        retryTemplate.registerListener(myRetryListener);
        return retryTemplate;
    }
}

最后调用重试方法。

@Service
public class RetryService {

    @Autowired
    private RetryTemplate retryTemplate;
    public void invokeApiWithRetry() {
        retryTemplate.execute(context -> {
            callApiMethod();
            return null;
        });
    }

    @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000))
    private void callApiMethod() {
        // 调用外部API的代码
    }
}

这时候调用失败时会重试,并且在重试发生出发监听,打印相应的异常日志。

第二种:使用网络工具的内置重试机制。
比如我们使用Apche HttpClient调用第三方接口时,它其实内置了相关的重试机制
在5.x的版本时:

 CloseableHttpClient httpClient = HttpClients.custom()
                .setRetryStrategy(new DefaultHttpRequestRetryStrategy(3,NEG_ONE_SECOND))
                .build();

在上面的示例代码中,我们使用DefaultHttpRequestRetryStrategy来创建一个重试机制,最大重试次数为3次。如果请求失败,则会自动重试。

当然:Apache HttpClient还支持自定义重试策略,我们可以根据需要,通过实现RetryStrategy接口,自定义重写逻辑,如下:

CloseableHttpClient httpClient = HttpClients.custom()
        .setRetryStrategy((response, executionCount, context) -> {
            if (executionCount > 3) {
                // 如果重试次数超过3次,则放弃重试
                return false;
            }
            int code = response.getCode();
            if (code >= 500 && code < 600) {
                // 如果遇到服务器错误状态码,则进行重试
                return true;
            }
            // 其他情况不进行重试
            return false;
        }) .build();

总结:
在请求重试的时候,我们也要注意一些关键点,以免因为重试,引发更多的问题,以下这些点我们需要考虑:
1.合理设置重试次数和重试间隔时间,避免频繁地发送请求,同时也不要设置过大的重试次数,以免影响系统的性能和响应时间。

2.在使用重试机制时,需要注意不要陷入死循环。如果请求一直失败,重试次数一直增加,可能会导致系统崩溃或者资源耗尽等问题。

3.考虑接口幂等性:如果请求是写操作,那么在重试时需要谨慎处理。
在重试过程中,需要考虑接口并发的问题,如果多个线程同时进行重试,可能会导致请求重复发送或请求顺序混乱等问题。可以使用锁或者分布式锁来解决并发问题。

  • 16
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜空下的星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值