重试机制-spring-retry、guava-retry
  kIvChpdcRkmZ 2023年11月02日 59 0


重试机制是什么?

网络重试机制是用于在网络通信中处理失败的请求。接口重试可以在一定的时间间隔内多次尝试发送相同的请求,直到请求成功或达到最大重试次数为止。

为什么要重试?

1. 提高请求的成功率:网络通信中可能会出现各种问题,如网络延迟、连接超时、服务器错误等。通过接口重试机制,可以尝试多次发送请求,增加请求成功的可能性。

2. 处理瞬时故障:有时候,请求失败是由于短暂的网络故障或服务器负载过高等瞬时问题引起的。通过接口重试,可以在稍后的尝试中成功发送请求,而无需手动干预。

3. 自动化处理:接口重试可以自动处理请求失败的情况,无需手动干预。这样可以减少开发人员的工作量,并提高系统的稳定性和可靠性。

注意:接口重试并不是万能的解决方案,有时候请求失败可能是由于永久性的问题,如无效的请求参数或者权限不足等。在设计接口重试机制时,需要考虑到这些情况,并设置合理的重试策略和最大重试次数。

重试的场景有哪些?

网络不稳定导致请求失败;

服务端繁忙,导致响应时间过长;

服务端出现故障,导致请求失败;

传参错误等错误,导致请求失败;

第三方接口调用失败,例如:钉钉、微信、权限等。

如何进行重试?

①、固定次数重试

设置一个固定的重试次数,在每次请求失败时都重新发送请求,直到达到最大重试次数或请求成功为止。

②、spring-retry

spring提供的请求重试组件,根据配置的重试策略进行重试

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

开启重试功能:

在启动类或者配置类上添加 @EnableRetry 注解

在需要重试的方法上添加 @Retryable 注解:标志当前方法使用重试机制

@Backoff:等待多久开始重试(指定重试的次数、时间间隔)

默认重试次数是3次,重试间隔是1s

@Retryable(maxAttempts = 3,backoff = @Backoff(delay = 2000,multiplier = 2))

@Recover:当重试达到指定次数之后,会调用指定的方法来进行日志记录等操作

@Recover
 public void recover(RuntimeException  e){
    System.out.println("达到最大重试次数"+e);
}

注意:@Recover 注解标记的方法必须和被 @Retryable 标记的方法在同一个类中

代码演示:

@Service
public class SpringRetryServiceImpl {
    @Autowired
    private LoginServiceImpl loginService;


    @Retryable(maxAttempts = 3,backoff = @Backoff(delay = 2000,multiplier = 2))
    public String getUserInfo(String id) throws Exception {
        System.out.println("开始时间"+System.currentTimeMillis());

        JSONObject bodyJson = loginService.getUserService(id);
        if (!bodyJson.get("code").equals(200)) {
            throw new Exception("失败");
        }
        return "调用成功";
    }

    @Recover
    public void recover(Exception e){
        System.out.println("达到最大重试次数"+e);
    }
}

 ③、guava-retry

能够根据 返回值 来判断是否需要重试

@Service
public class GuavaImpl {
    @Autowired
    private LoginServiceImpl loginService;

    public String getUserInfo(String id) throws Exception {

        Callable<String> task = new Callable<String>() {
            @Override
            public String call() throws Exception {
                JSONObject bodyJson = loginService.getUserService(id);
                if (!bodyJson.get("code").equals(200)) {
                    throw new Exception("失败");
                }
                return "调用成功";
            }
        };

        Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
                //无论出现什么异常,都进行重试
                .retryIfException()
                //返回结果为 error时,进行重试
                .retryIfResult(result -> Objects.equals(result, "error"))
                //重试等待策略:等待 2s 后再进行重试
                .withWaitStrategy(WaitStrategies.fixedWait(2, TimeUnit.SECONDS))
                //重试停止策略:重试达到 3 次
                .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                .withRetryListener(new RetryListener() {
                    @Override
                    public <V> void onRetry(Attempt<V> attempt) {
                        System.out.println("RetryListener: 第" + attempt.getAttemptNumber() + "次调用");
                    }
                })
                .build();
        try {
            retryer.call(task);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "调用成功";
    }
}

超时:服务不要一直在服务端进行堆积(影响新请求处理/系统崩溃),请求超过设置时间没有被处理就取消或抛异常

重试:和超时绑定,多次发送相同

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  NT5NRjELxLp1   2024年04月29日   70   0   0 PHP
  yThMa20bw7iV   2024年02月19日   71   0   0 PHP
  iyViKl6W0XQr   2024年05月17日   53   0   0 PHP
  NT5NRjELxLp1   2024年03月14日   83   0   0 PHP
kIvChpdcRkmZ