【问题标题】:How to consume spring web client response如何使用 Spring Web 客户端响应
【发布时间】:2020-10-17 23:05:43
【问题描述】:

我在 Spring 应用程序中使用 Web 客户端

我在做同样的事情时遇到了内存泄漏问题

我正在使用以下代码从服务获取非 2XX 响应的响应正文:

return client.get()
                .uri(uriString)
                .headers(ServiceCommonUtil.getHttpHeaderConsumer(headersMap))
                .exchange()
                .flatMap(clientResponse -> {
                    try {
                        clientResponse.body((clientHttpResponse, context) ->
                                clientHttpResponse.getBody());
                        logResponseStatus(clientResponse.statusCode(), serviceName);
                        return clientResponse.bodyToMono(String.class);
                    } catch (Exception e) {
                        return null;
                    }

                })

以后订阅者使用 subscribe/ 错误块来处理这个响应。

responseMono.subscribe(response -> {
    //process response string
},error->{
    //process error response
});

我的问题是,如果我在 responseMono 上使用 dispose 方法,则处理需要很长时间,而没有它我将面临内存泄漏问题。 我在这里做错了吗?

【问题讨论】:

    标签: spring-boot spring-webflux spring-webclient


    【解决方案1】:

    看来你有点复杂了。为什么在 clientResponse lambda 中有一个 try/catch 块?如果你的logResponseStatus 抛出一个检查异常然后在那里处理它。我建议从简单的开始。

    例 1:

    Mono<String> stringMono = webClient.get().uri("test").header("head", "value").exchange().flatMap(clientResponse->clientResponse.bodyToMono(String.class));
    stringMono.subscribe(System.out::println);
    

    例 2:

    Mono<String> stringMono = webClient.get().uri("test").header("head", "value").exchange().flatMap(clientResponse->clientResponse.body(BodyExtractors.toMono(String.class)));
    stringMono.subscribe(System.out::println);
    

    例 3:

    Mono<String> stringMono = webClient.get().uri("test").header("head", "value").retrieve().bodyToMono(String.class);
    stringMono.subscribe(System.out::println);
    

    对于日志记录,最好使用ExchangeFilterFunctions。见How to intercept a request when using SpringBoot WebClient

    【讨论】:

    • 是的 try catch 实际上是不必要的.. 我想但不能像我想要的那样进行检索,即使在 4xx/5xx 的情况下也是如此。所以在 Ex1/Ex2 中只有一个基本的 q,做我需要调用 releaseBody 或 dispose ,否则他们将在内部负责释放 body 并将连接返回到池?
    • 不,不用担心连接问题。这是内部处理的。您不能在 Mono/Flux 或其他任何情况下返回 null,如果您必须有一个 try catch(不是),那么您将需要返回 Mono.error(exception)
    【解决方案2】:

    是的,实际上你并没有在抛出异常的情况下消费响应。

    如果您想使用exchange(),您的责任就是消耗响应。 见:docs

    在 'ClientResponse` api 中查看 toBodilessEntity()/ releaseBody()

    【讨论】:

    • 知道了..所以你说我只是使用 clientResponse->clientResponse.bodyToMono(String.class) 而不是 try/catch 将这个发布主体或者我仍然必须使用 releaseBody()跨度>
    • 是的,它会自动释放body
    猜你喜欢
    • 2021-08-24
    • 2018-04-22
    • 2019-01-29
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-31
    相关资源
    最近更新 更多