发送高流量时Web客户端超时异常

问题描述 投票:0回答:1

我使用reactor-netty中的WebClient来调用下游, 下游延迟为 15 秒才响应。 我尝试使用 Jmetter 每秒发送 20 个请求,其中一半返回 500,并出现 WebClient 超时异常,如下所示:

java.util.concurrent.TimeoutException: Webclient timeout
    at********.Test.lambda$call$1(Test.java:37)
    at reactor.core.publisher.Mono.lambda$onErrorResume$32(Mono.java:3887)
    at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94)
    at reactor.core.publisher.SerializedSubscriber.onError(SerializedSubscriber.java:124)
    at reactor.core.publisher.FluxTimeout$TimeoutMainSubscriber.handleTimeout(FluxTimeout.java:295)
    at reactor.core.publisher.FluxTimeout$TimeoutMainSubscriber.doTimeout(FluxTimeout.java:280)
    at reactor.core.publisher.FluxTimeout$TimeoutTimeoutSubscriber.onNext(FluxTimeout.java:419)
    at reactor.core.publisher.FluxOnErrorReturn$ReturnSubscriber.onNext(FluxOnErrorReturn.java:162)
    at reactor.core.publisher.MonoDelay$MonoDelayRunnable.propagateDelay(MonoDelay.java:271)
    at reactor.core.publisher.MonoDelay$MonoDelayRunnable.run(MonoDelay.java:286)
    at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:68)
    at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:28)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.util.concurrent.TimeoutException: Did not observe any item or terminal signal within 20000ms in 'flatMap' (and no fallback has been configured)
    ... 13 common frames omitted

步骤重现: 使用 JMeter 每秒向 GET /test API 发送 20 个请求

@RestController
@RequiredArgsConstructor
public class Test {

  private final WebClient.Builder webClientBuilder;

  public Mono<?> call() {
    return webClientBuilder.build().method(HttpMethod.GET)
        .uri("http://localhost:8080/ms-test-webclient/delay")
        .headers(httpHeaders -> httpHeaders.set("Content-Type", "application/json"))
        .retrieve()
        .toEntity(String.class)
        .flatMap(Mono::just)
        .timeout(Duration.ofSeconds(20))
        .onErrorResume(TimeoutException.class, ex -> {
          String message = "Webclient timeout";
          return Mono.error(new TimeoutException(message).initCause(ex));
        });
  }

  @GetMapping("test")
  public Mono<?> test() {
    return call();
  }

  @GetMapping("delay")
  @SneakyThrows
  public String delayresponse() {
    Thread.sleep(15000);
    return "success";
  }
}

它应该返回 200 而不是 500 以及 Web 客户端超时异常。

spring-webflux project-reactor reactor-netty
1个回答
0
投票

在使用项目reactor时不应该使用

Thread.sleep
,因为这会阻塞整个线程,并且无法重用。 使
delay
方法看起来像这样:

  @GetMapping("delay")
  @SneakyThrows
  public Mono<String> delayresponse() {
    return Flux.interval(Duration.ofSeconds(15))
          .next()
          .map(any -> "success");
  }
© www.soinside.com 2019 - 2024. All rights reserved.