一、前言
在实际项目中,往往在某些特定的场景下,我们需要实现接口调用异常的重试机制,比如在跨平台的业务中,需要调用第三方接口实现某些功能,难免会遇到一些网络问题,这时候需要加入重试机制了。
二、如何实现?
第一种:基于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 {@Beanpublic 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 {@Overridepublic <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 {@Autowiredprivate MyRetryListener myRetryListener;@Beanpublic 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 {@Autowiredprivate 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.考虑接口幂等性:如果请求是写操作,那么在重试时需要谨慎处理。
在重试过程中,需要考虑接口并发的问题,如果多个线程同时进行重试,可能会导致请求重复发送或请求顺序混乱等问题。可以使用锁或者分布式锁来解决并发问题。