spring-boot - Spring Boot Webclient 抛出 readtimeout 错误

标签 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);
        }
    }

最佳答案

如前所述on the Spring Framework issue you've opened (谢谢!),这似乎不是框架中的错误。

混淆来自于同时运行多个 Web 客户端请求并添加 log 的事实。响应式管道上的运算符(operator)以获取更多信息,日志使您认为即使刚刚发出请求,也会触发读取超时。

如果我没记错的话,您在日志中看到的后缀号如 reactor.Mono.SwitchIfEmpty.48759与订阅者绑定(bind)。

在您的情况下,这意味着

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);

我没有任何读取超时。所以你的应用程序中的某些东西必须配置这样的超时。

关于spring-boot - Spring Boot Webclient 抛出 readtimeout 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53786424/

相关文章:

java - 如何测试更新方法?

java - 通过查询模式通过子对象访问父对象的 protected 字段

maven - 使用 “spring-boot-starter-parent”时如何在Maven中使用较低的Elastic搜索版本

spring - 使用 Spring Webflux 恢复文件下载以及 Spring 中的静态文件服务

java - 如何使用 spring webflux 上传和读取文本文件?

spring-boot - 使用 Open API 进行测试时,带有 HttpEntity 的 Spring Rest Controller API 获取空主体

java - H2中使用Spring的列表类型字段

java - Spring Boot Thymeleaf 字符编码为 UTF-8

java - 带有 MySql 的 Spring boot 响应式(Reactive) (Webflux)

spring - 对假客户端的响应式(Reactive)支持