Spring webclient - 每次重试后增加超时持续时间

问题描述

我正在寻找一种方法增加网络客户端调用连续重试后​​超时的持续时间。

例如,我希望第一个请求在 50 毫秒后超时,第一次重试将在 500 毫秒后超时,第二次也是最后一次重试的超时持续时间为 5000 毫秒。

我不知道该怎么做。我只知道如何将超时值设置为所有重试的固定持续时间。

例如

public Flux<Employee> findAll() 
{
    return webClient.get()
        .uri("/employees")
        .retrieve()
        .bodyToFlux(Employee.class)
        .timeout(Duration.ofMillis(50))
        .retry(2);
}

解决方法

您可以将退避和超时逻辑抽象为一个单独的实用程序函数,然后只需在发布商上调用 transform()

在您的情况下,您似乎在追求基本的退避功能 - 取一个初始超时值,然后将其乘以一个因子,直到达到最大值。我们可以这样实现:

public <T> Flux<T> retryWithBackoffTimeout(Flux<T> flux,Duration timeout,Duration maxTimeout,int factor) {
    return mono.timeout(timeout)
            .onErrorResume(e -> timeout.multipliedBy(factor).compareTo(maxTimeout) < 1,e -> retryWithBackoffTimeout(mono,timeout.multipliedBy(factor),maxTimeout,factor));
}

...但这当然可以是您喜欢的任何类型的超时逻辑。

使用该实用程序函数后,您的 findAll() 方法变为:

public Flux<Employee> findAll()
{
    return webClient.get()
            .uri("/employees")
            .retrieve()
            .bodyToFlux(Employee.class)
            .transform(m -> retryWithBackoffTimeout(m,Duration.ofMillis(50),Duration.ofMillis(500),10));
}
,

您是否探索过@Retryable?如果没有,那么这里是选项。添加这个依赖

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>1.2.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.1.5.RELEASE</version>
</dependency>

注释你的主类

@EnableRetry
public class MainClass{
    ...
}

然后注释您调用调用的事务

public interface BackendAdapter {
 
    @Retryable(
    value = {YourCustomException.class},maxAttempts = 4,backoff = @Backoff(random = true,delay = 1000,maxDelay = 5000,multiplier = 2)
)
    public String getBackendResponse(boolean simulateretry,boolean simulateretryfallback);
 }

如果您将延迟设置为 1000 毫秒,将 maxDelay 设置为 5000 毫秒并将乘数设置为 2,则重试时间将类似于以下 4 次尝试:

Retry 1 — 1605
Retry 2 — 2760
Retry 3 — 7968
Retry 4 — 14996