spring-boot重试机制:Guava-Retrying

简介: 在业务开发中,请求第三方接口时常因网络问题导致失败,此时可使用重试机制解决。本文介绍基于Guava实现的guava-retrying,通过封装HTTP请求工具类并结合重试策略,提升接口调用稳定性。内容涵盖工具类编写、重试配置及监听处理,适用于Java开发者优化系统健壮性。

在我们正常的业务开发中,不免会发生请求第三方接口的应用场景,但由于网络不稳定的原因经常会发生一些问题,比如:请求虽然发出去,但返回的确实服务器繁忙、或者干脆没有返回信息等等,这时可以应用重试机制来解决这个问题,常用的重试有java Retry、springboot Retry与guava-retrying。这次主要介绍一下guava-retrying。guava-retrying是基于谷歌的核心类库guava的重试机制实现,本文一个常用的post与get的方法来介绍guava retrying重试机制的使用。

首先我们写一个http请求的工具类,其中有post与get方法

java

体验AI代码助手

代码解读

复制代码

public abstract class HttpUtil {
    public HttpUtil() {
    }


    protected JSONObject get(String requestUrl) throws IOException {
        StringBuilder buffer = new StringBuilder();a
        URL url = new URL(requestUrl);
        HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
        httpsURLConnection.setRequestProperty("accept", "*/*");
        httpsURLConnection.setRequestProperty("connection", "Keep-Alive");
        httpsURLConnection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
        httpsURLConnection.setRequestMethod("GET");
        httpsURLConnection.connect();

        InputStream inputStream = httpsURLConnection.getInputStream();
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

        String str;
        while ((str = bufferedReader.readLine()) != null) {
            buffer.append(str);
        }
        bufferedReader.close();
        inputStreamReader.close();
        inputStream.close();
        httpsURLConnection.disconnect();
        return JSONObject.fromObject(buffer.toString());
    }

    protected JSONObject post(String requestUrl, String outputStr) throws Exception {
        StringBuilder buffer = new StringBuilder();
        TrustManager[] tm = new TrustManager[]{new MyX509TrustManager()};
        SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
        sslContext.init(null, tm, new SecureRandom());
        SSLSocketFactory ssf = sslContext.getSocketFactory();
        URL url = new URL(requestUrl);
        HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
        httpUrlConn.setSSLSocketFactory(ssf);
        httpUrlConn.setRequestProperty("Content-type", "application/json");
        httpUrlConn.setDoOutput(true);
        httpUrlConn.setDoInput(true);
        httpUrlConn.setUseCaches(false);
        httpUrlConn.setReadTimeout(10000);
        httpUrlConn.setConnectTimeout(10000);
        httpUrlConn.setRequestMethod("POST");
        if (null != outputStr) {
            OutputStream outputStream = httpUrlConn.getOutputStream();
            outputStream.write(outputStr.getBytes(Charset.forName("UTF-8")));
            outputStream.close();
        }

        InputStream inputStream = httpUrlConn.getInputStream();
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

        String str;
        while ((str = bufferedReader.readLine()) != null) {
            buffer.append(str);
        }

        bufferedReader.close();
        inputStreamReader.close();
        inputStream.close();
        httpUrlConn.disconnect();
        return JSONObject.fromObject(buffer.toString());
    }

    private static class MyX509TrustManager implements X509TrustManager {
        private MyX509TrustManager() {
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType) {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }
}

接下来我们需要写一个类来继承HttpUtil工具类并重写其中的post方法与get方法

java

体验AI代码助手

代码解读

复制代码

public class HttpService extends HttpUtil {
    @Override
    protected JSONObject post(String requestUrl, String outputStr) throws Exception {
        return super.post(requestUrl, outputStr);
    }

    @Override
    protected JSONObject get(String requestUrl) throws Exception{
        return super.get(requestUrl);
    }
}

增加重试机制的策略

java

体验AI代码助手

代码解读

复制代码

    private final Retryer<JSONObject> retryer = RetryerBuilder.<JSONObject>newBuilder()
            .retryIfExceptionOfType(Exception.class) //根据异常重试
            .retryIfException() //发生异常重试
            .retryIfResult(Predicates.isNull()) //返回接口为null需要重试
            .withWaitStrategy(WaitStrategies.fixedWait(3, TimeUnit.SECONDS)) //3毫秒后重试
            .withStopStrategy(StopStrategies.stopAfterAttempt(3)) //重试次数
            .withRetryListener(new MyRetryListener()) //注册监听 监听这里我们最后说
            .build();

接下来将重试的机制配置到方法里,由于post与get的方法基本一致所以这里只列举post

java

体验AI代码助手

代码解读

复制代码

    @Override
    public JSONObject get(String requestUrl) {
        Callable<JSONObject> callable = () -> {
            // TODO: 业务逻辑的实现
            return super.get(requestUrl);
        };
        try {
            return retryer.call(callable);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

java

体验AI代码助手

代码解读

复制代码

/**
 * @Author fallrain
 * @Date 2021/3/10 15:12
 * @description:重试失败监听器,监听可以使我们做好错误日志的整理,以便后期系统的优化
 * @Version 1.0
 */
@Log4j2
public class MyRetryListener implements RetryListener {
    @Override
    public <V> void onRetry(Attempt<V> attempt) {
        if (attempt.getAttemptNumber() == 1) return;
        log.error("第{}次重试", attempt.getAttemptNumber());
        log.error("重试原因:{}", attempt.getExceptionCause().toString());
        if(attempt.getAttemptNumber()==3){
            // TODO: 若第三次重试还是存在错误,则记录错误信息
        }
    }
}

java

体验AI代码助手

代码解读

复制代码

//在使用时我们可以直接new一个出来使用
private HttpUtil httpUtil=new HttpService();
//也可以通过springboot IOC容器注入一个使用
@Autowired
public ServiceImpl(HttpUtil httpUtil) {
    this.httpUtil = httpUtil;
}

java

体验AI代码助手

代码解读

复制代码

//完整代码
@Service
public class HttpService extends HttpUtil {

    public HttpService() {
    }
    private final Retryer<JSONObject> retryer = RetryerBuilder.<JSONObject>newBuilder()
            .retryIfExceptionOfType(Exception.class) //根据异常重试
            .retryIfException()
            .retryIfResult(Predicates.isNull()) //返回接口为null需要重试
            .withWaitStrategy(WaitStrategies.fixedWait(3, TimeUnit.SECONDS)) //3毫秒后重试
            .withStopStrategy(StopStrategies.stopAfterAttempt(3)) //重试次数
            .withRetryListener(new MyRetryListener()) //注册重试监听
            .build();

    @Override
    public JSONObject post(String requestUrl, String outputStr) {
        Callable<JSONObject> callable = () -> super.post(requestUrl, outputStr);
        try {
            return retryer.call(callable);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public JSONObject get(String requestUrl) {
        Callable<JSONObject> callable = () -> super.get(requestUrl);
        try {
            return retryer.call(callable);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}


转载来源:https://juejin.cn/post/7485349659743453224

相关文章
|
Java 数据库连接 Spring
如何在Spring Boot中使用`@Retryable`注解来实现重试机制?
如何在Spring Boot中使用`@Retryable`注解来实现重试机制?
1552 0
如何在Spring Boot中使用`@Retryable`注解来实现重试机制?
|
XML Java UED
使用 Spring Boot 实现重试和补偿功能:从理论到实践
【6月更文挑战第17天】在分布式系统中,服务之间的调用可能会因为网络故障、服务器负载等原因偶尔失败。为了提高系统的可靠性和稳定性,我们经常需要实现重试和补偿功能。
665 6
|
Java Android开发
jvisualvm分析jvm内存溢出
jvisualvm分析jvm内存溢出
1641 0
jvisualvm分析jvm内存溢出
|
5月前
|
机器学习/深度学习 人工智能 缓存
万字综述,讲一讲这两年大模型这整个领域到底发展了哪些方面
本文深入探讨了自2023年GPT-4发布以来,大型语言模型(LLM)领域的发展趋势及其技术演进路径。
万字综述,讲一讲这两年大模型这整个领域到底发展了哪些方面
|
缓存 Java Sentinel
Springboot 中使用 Redisson+AOP+自定义注解 实现访问限流与黑名单拦截
Springboot 中使用 Redisson+AOP+自定义注解 实现访问限流与黑名单拦截
|
5月前
|
人工智能 前端开发 安全
Java开发不可不知的秘密:类加载器实现机制
类加载器是Java中负责动态加载类到JVM的组件,理解其工作原理对开发复杂应用至关重要。本文详解类加载过程、双亲委派模型及常见类加载器,并介绍自定义类加载器的实现与应用场景。
252 4
|
6月前
|
人工智能 Java Scala
Springboot捕获feign抛出的异常
本文探讨了在使用Springboot与Feign客户端时,如何有效捕获接口异常的问题。由于全局异常无法直接捕获Feign抛出的异常,文章提供了具体解决方案:通过定义自定义异常类`BusinessException`,结合`ErrorDecoder`对Feign请求异常进行处理,或在全局异常捕获中添加特定处理器。示例代码详细展示了配置与实现步骤,帮助开发者更好地应对Feign客户端的异常处理需求。
320 2
|
XML JavaScript Java
Spring Retry 教程
Spring Retry 是 Spring 提供的用于处理方法重试的库,通过 AOP 提供声明式重试机制,不侵入业务逻辑代码。主要步骤包括:添加依赖、启用重试机制、设置重试策略(如异常类型、重试次数、延迟策略等),并可定义重试失败后的回调方法。适用于因瞬时故障导致的操作失败场景。
347 1
Spring Retry 教程
|
12月前
|
JavaScript Java Kotlin
深入 Spring Cloud Gateway 过滤器
Spring Cloud Gateway 是新一代微服务网关框架,支持多种过滤器实现。本文详解了 `GlobalFilter`、`GatewayFilter` 和 `AbstractGatewayFilterFactory` 三种过滤器的实现方式及其应用场景,帮助开发者高效利用这些工具进行网关开发。
1636 1
|
安全 Java 编译器
springboot 整合表达式计算引擎 Aviator 使用示例详解
本文详细介绍了Google Aviator 这款高性能、轻量级的 Java 表达式求值引擎
1655 6

热门文章

最新文章