Spring webclient - 每次重试后增加超时持续时间
Spring webclient - increase timeout duration after each retry
我正在寻找一种方法来增加连续重试 webclient 调用后的超时持续时间。
例如,我希望第一次请求在 50 毫秒后超时,第一次重试将在 500 毫秒后超时,第二次也是最后一次重试的超时持续时间为 5000 毫秒。
我不知道该怎么做。我只知道如何将所有重试的超时值设置为固定持续时间。
例如
public Flux<Employee> findAll()
{
return webClient.get()
.uri("/employees")
.retrieve()
.bodyToFlux(Employee.class)
.timeout(Duration.ofMillis(50))
.retry(2);
}
你探索过@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>
注释您的 Main Class
@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 毫秒,将最大延迟设置为 5000 毫秒,并将倍增器设置为值 2,则重试时间将类似于以下 4 次尝试:
Retry 1 — 1605
Retry 2 — 2760
Retry 3 — 7968
Retry 4 — 14996
您可以将退避和超时逻辑抽象到一个单独的实用程序函数中,然后只需在您的发布商上调用 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));
}
我正在寻找一种方法来增加连续重试 webclient 调用后的超时持续时间。
例如,我希望第一次请求在 50 毫秒后超时,第一次重试将在 500 毫秒后超时,第二次也是最后一次重试的超时持续时间为 5000 毫秒。
我不知道该怎么做。我只知道如何将所有重试的超时值设置为固定持续时间。
例如
public Flux<Employee> findAll()
{
return webClient.get()
.uri("/employees")
.retrieve()
.bodyToFlux(Employee.class)
.timeout(Duration.ofMillis(50))
.retry(2);
}
你探索过@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>
注释您的 Main Class
@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 毫秒,将最大延迟设置为 5000 毫秒,并将倍增器设置为值 2,则重试时间将类似于以下 4 次尝试:
Retry 1 — 1605
Retry 2 — 2760
Retry 3 — 7968
Retry 4 — 14996
您可以将退避和超时逻辑抽象到一个单独的实用程序函数中,然后只需在您的发布商上调用 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));
}