Skip to main content
Version: 1.5.x

重试机制

Forest请求在发送失败的情况下会触发重试机制,重试的次数限制、时间间隔、触发条件全部都可以配置

配置全局重试信息#

application.yml文件中进行配置

application.yml
# 全局配置下,所有请求的默认重试信息按此配置进行
forest:    max-retry-count: 3     # 最大请求重试次数,默认为 0 次    max-retry-interval: 10 # 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒

application.properties文件中进行配置

application.propperties
# 全局配置下,所有请求的默认重试信息按此配置进行
# 最大请求重试次数,默认为 0 次forest.max-retry-count=3# 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒forest.max-retry-interval=10 

如果是非 Spring Boot 项目,可以通过 ForestConfiguration 对象进行配置

// 获取全局默认配置对象ForestConfiguration configuration = Forest.config();// 最大请求重试次数,默认为 0 次configuration.setMaxRetryCount(3);// 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒configuration.setMaxRetryInterval(10);

使用@Retry注解#

在方法上挂上@Retry注解#

public interface MyClient {    // maxRetryCount 为最大重试次数,默认为 0 次    // maxRetryInterval 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒    @Get("/")    @Retry(maxRetryCount = "3", maxRetryInterval = "10")    String sendData();}

这里的@Retry注解设置了两个属性:

  • maxRetryCount: 请求的最大重试次数,当重试次数大于该属性,将停止触发请求重试流程,默认为0次,即不会触发重试
  • maxRetryInterval: 请求的最大重试时间间隔,单位为毫秒,默认为0毫秒,即没有时间间隔

当调用该接口的sendData()方法后,若请求失败就会不断进行重试,直到不满足重试条件为止 (即请求成功,或达到最大请求次数限制)

接口上使用@Retry注解#

@Retry注解也可以挂在interface接口类上,代表其下的所有请求方法都设置为此重试配置

// maxRetryCount 为最大重试次数,默认为 0 次// maxRetryInterval 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒// 该接口下每个方法都以此为请求重试配置@Retry(maxRetryCount = "3", maxRetryInterval = "10")public interface MyClient {        @Get("/test1")    String sendData1();
    @Get("/test2")    String sendData2();}

此时,不管调用sendData1()还是sendData2()方法,都会按最大重试3次,最大重试时间间隔10ms为重试属性

重试器#

Retryer 重试器,即重试策略,可以设定每次重试请求之间的时间间隔

Forest 默认重试器类为 com.dtflys.forest.retryer.BackOffRetryer,它是依据二进制退避算法的重试策略类

若配置该重试器,重试过程如下:

  • 第一次重试与第一次请求之间间隔 0的2次方 * 1s, 即0s
  • 第二次重试与第一次重试之间间隔 1的2次方 * 1s, 即1s
  • 第三次次重试与第二次重试之间间隔 2的2次方 * 1s, 即4s
  • 后面几次重试时间间隔以此类推,直到达到最大请求次数后停止重试
  • 每次时间间隔不能大于 maxRetryInterval, 若 maxRetryInterval 设置为 10, 则每次间隔只能为 10ms

您也可以自定义重试器

// 自定义重试器// 继承 BackOffRetryer 类public class MyRetryer extends BackOffRetryer {
    public MyRetryer(ForestRequest request) {        super(request);    }
    /**     * 重写 nextInterval 方法     * 该方法用于指定每次重试的时间间隔     * @param currentCount 当前重试次数     * @return 时间间隔 (时间单位为毫秒)     */    @Override    protected long nextInterval(int currentCount) {        // 每次重试时间间隔恒定为 1s (1000ms)        return 1000;    }}

然后,再通过@Retryer注解绑定该自定义重试器类

public interface MyClient {    // maxRetryCount 为最大重试次数,默认为 0 次    // maxRetryInterval 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒    // @Retryer 注解绑定自定义的 MyRetryer 重试器类    // 将按照自定义的重试策略处理重试间隔时间    @Get("/")    @Retry(maxRetryCount = "3", maxRetryInterval = "10")    @Retryer(MyRetryer.class)    String sendData();}

@Retryer注解同样也可以挂在 interface 类上,这里不再赘述。

重试条件#

Forest 请求的重试条件有两种设置模式:

这两种模式分别对应于两种不同的重试流程:

重试流程#

  1. 请求失败后的重试流程
请求失败  ✔ └── 是否未达到请求最大重试次数 (maxRetryCount)  ✔      ├── 执行 OnRetry 回调函数      ├── 执行拦截器中的 onRetry 方法      ├── 发送重试请求      └── 回到第一步,重试请求是否成功
  1. 请求成功后的重试流程
请求成功  ✔ └── 是否满足重试条件 (自定义 RetryWhen 接口类条件)  ✔      └── 是否未达到请求最大重试次数 (maxRetryCount)  ✔           ├── 执行 OnRetry 回调函数           ├── 执行拦截器中的 onRetry 方法           ├── 发送重试请求           └── 回到第一步,重试请求是否成功,并且是否满足重试条件

使用@Success注解设置重试条件#

一般情况只会走第1种重试流程,即直通过请求的成功/失败来判断是否重试,逻辑很简单:请求成功不重试,失败就重试

此时,可以配合@Success注解和@Retry注解组合使用


public interface MyClient {    // maxRetryCount 为最大重试次数,默认为 0 次    // maxRetryInterval 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒    // 同时请求成功/失败/重试的判定条件    // 设置为自定义的 MySuccessCondition 条件类    @Get("/")    @Retry(maxRetryCount = "3", maxRetryInterval = "10")    @Success(condition = MySuccessCondition.class)    String sendData();}

这种方式可以同时设置重试最大次数、间隔时间、以及自定义的成功/失败/重试条件。

使用 RetryWhen 接口实现重试条件#

但有些特殊情况,需要在请求成功的情况下也重试,满足一定业务条件后才停止重试,这种情况就需要 RetryWhen 重试条件上场了

先定义自定义请求重试实现类

// 自定义重试条件类// 需要实现 RetryWhen 接口public class MyRetryCondition implements RetryWhen {    /**     * 请求重试条件     * @param req Forest请求对象     * @param res Forest响应对象     * @return true 重试,false 不重试     */    @Override    public boolean retryWhen(ForestRequest req, ForestResponse res) {        // 响应状态码为 203 就重试        return res.statusIs(203);    }}

然后,通过@Retry注解的condition属性指定该类

public interface MyClient {    // maxRetryCount 为最大重试次数    // maxRetryInterval 为最大重试时间间隔, 单位为毫秒    @Get("/")    @Retry(maxRetryCount = "3", maxRetryInterval = "10", condition = MyRetryCondition.class)    String sendData();}

若发送请求后,服务端返回203状态码,就不断触发重试,直到服务端不返回203,或达到最大重试次数,停止重试。 若最后一次重试服务端发送的还是203,则认为请求成功,执行onSuccess

拦截器onRetry方法#

拦截器的onRetry方法会在触发重试时,发送重试请求前被调用

public class MyRetryInterceptor implements Interceptor<Object> {
    /**     * 在请重试前调用 onRetry 回调函数     *     * @param req Forest请求对象     * @param res Forest响应对象     */    @Override    public void onRetry(ForestRequest req, ForestResponse res) {        // req.getCurrentRetryCount() 获取请求当前重试次数        System.out.println("要重试了!当前重试次数:" + req.getCurrentRetryCount());    }}
文档导航

关于如何使用拦截器,请参见《拦截器