Springboot WebClient抛出读取超时错误

时间:2018-12-14 20:21:40

标签: spring-boot spring-webflux

Spring Webclient抛出大量读取超时(每秒负载1000个请求)。我正在使用Springboot版本2.1.1.RELEASE。请找到下面的代码,如果我缺少任何配置,请告诉我:

@Bean
public WebClient webClient() {
    return WebClient.builder().build();
}

public Mono<String> post(String url, JSONObject body) {

    Mono<String> result = webClient.post().uri(url)
            .contentType(MediaType.APPLICATION_JSON)
            .accept(MediaType.APPLICATION_JSON_UTF8)
            .body(BodyInserters.fromObject(body))
            .exchange()
            .flatMap { clientResponse ->
        return handleResponse(clientResponse)
    }
    return result;
}

private Mono<String> handleResponse(ClientResponse clientResponse) {
         if (clientResponse.statusCode().is4xxClientError() || clientResponse.statusCode().is5xxServerError()) {
            return clientResponse.bodyToMono(String.class)
                    .flatMap { errorBody ->
                return Mono.error(new CustomException(errorBody, clientResponse.statusCode().value()))
            }
        } else {
            return clientResponse.bodyToMono(String.class);
        }
    }

2 个答案:

答案 0 :(得分:0)

可以检查要访问的资源是否未启用限制。 抱歉,我没有足够的声誉来发表评论。

答案 1 :(得分:0)

on the Spring Framework issue you've opened(感谢您!)说,这似乎不是Framework中的错误。

混淆来自以下事实:当同时运行多个Web客户端请求并在反应性管道上添加log操作符以获取更多信息时,日志使您认为即使请求被触发,读取超时也会触发刚制成。

如果我没记错的话,您在日志中看到的后缀编号(例如reactor.Mono.SwitchIfEmpty.48759)与订户相关。

就您而言,这意味着

13:55:50.287 [reactor-http-nio-6] INFO reactor.Mono.MapFuseable.49127 - | request(unbounded) 

13:55:50.312 [reactor-http-nio-6] ERROR reactor.Mono.SwitchIfEmpty.48759 - onError(

不是相同的HTTP请求。 Reactor在工作线程上调度任务,因此,当您看到事情在同一线程上顺序发生时,并不意味着这些工作单元正在同一订户上完成。

如果您遵循日志中的订户ID,则应该看到从请求数据到不获取数据之间的时间约为5秒。

不是最后一点,我创建了一个Reactor HTTP服务器,该服务器在10秒后发送响应正文:

HttpServer.create().host("localhost").port(8080).handle((req, res) -> {
    return res.sendString(Flux.just("Hello")
        .delayElements(Duration.ofSeconds(10)), StandardCharsets.UTF_8);
}).bindNow().onDispose().block();

还有一个获取此数据的WebClient:

String response = WebClient.create().get().uri("http://localhost:8080/")
    .retrieve().bodyToMono(String.class).log().block();
System.out.println(response);

我没有任何读取超时。因此,您的应用程序中一定有一些东西正在配置这样的超时。