【问题标题】:Getting: org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144获取:org.springframework.core.io.buffer.DataBufferLimitException:超出缓冲区最大字节数限制:262144
【发布时间】:2021-09-02 14:00:35
【问题描述】:

收到对 HTTP 请求的响应后,我收到了 DataBufferLimitException。我正在使用spring-boot-starter-parent:2.5.0、spring-cloud.version:2020.0.2。 我几乎尝试了这里(DataBufferLimitException: Exceeded limit on max bytes to buffer webflux error)和这里(configure spring.codec.max-in-memory-size When using ReactiveElasticsearchClient)描述的所有选项,但没有成功。还有什么我可以尝试的吗?这是我创建网络客户端的代码:

private WebClient buildWebClient(long custId) {
        return WebClient.builder()
                .clientConnector(createWebClientWithTimeout())
                // Add base url to all requests (callers only need to add the path and query params)
                .baseUrl(baseUrl)
                // Filter to add bearer token to auth header before sending request
                .filter((request, next) -> getToken(custId).map(setAuthHeader(request)).flatMap(next::exchange))
                // Filter to send the request, and try again if it has an auth error
                .filter((request, next) -> next.exchange(request).flatMap(clientResponse -> {
                    if (clientResponse.statusCode() == HttpStatus.UNAUTHORIZED) {
                        logger.error("Received 401 Unauthorized from linkedin for request: {} {} with X-LI-UUID header: {}", request.method(), request.url(), 
                                clientResponse.headers().header(LINKEDIN_HEADER));
                        // Retry once if auth failed
                        return clientResponse.bodyToMono(String.class)
                                .doOnNext(err -> logger.warn("Received 401 from linkedin; retrying once. Error body: {}", err))
                                .then(refreshToken(custId).map(setAuthHeader(request)).flatMap(next::exchange));
                    } else if (clientResponse.statusCode().isError()) {
                        logger.error("Received error status code: {} from linkedin for request: {} {} with X-LI-UUID header: {}", clientResponse.statusCode(), request.method(), 
                                request.url(), clientResponse.headers().header(LINKEDIN_HEADER));
                    } else {
                        logger.debug("Received status code: {} from linkedin for request: {} {}", clientResponse.statusCode(), request.method(), request.url());
                    }
                    // If not a 401, just return the response
                    return Mono.just(clientResponse);
                })).build();
    }

向属性添加 spring.codec.max-in-memory-size=16MB 不起作用,使用 ExchangeStrategies 显式设置值不起作用,实现 WebFluxConfigurer 不起作用。 这段代码在 spring-boot-starter-parent:2.1.6.RELEASE 上运行良好。 关于下一步我可以尝试什么的任何建议?

【问题讨论】:

    标签: spring-boot spring-webflux


    【解决方案1】:

    Spring Boot 为您预先配置了 WebClienter.Builder,这使得 spring.codec.max-in-memory-size 等设置最终起作用。

    要使用这个预配置的 WebClient.Builder,您需要将它注入到您的服务中,这看起来不像您在上面的示例中所做的那样。您似乎直接使用 WebClient.builder() 方法。

    此代码与应用程序属性 spring.codec.max-in-memory-size 一起可以工作:

    @Service
    public class Foo(WebClient.Builder injectedPreConfiguredBuilder) {
    
        private WebClient buildWebClient(long custId) {
                return injectedPreConfiguredBuilder
                        .clientConnector(createWebClientWithTimeout())
                        // Add base url to all requests (callers only need to add the path and query params)
                        .baseUrl(baseUrl)
                        // Filter to add bearer token to auth header before sending request
                        .filter((request, next) -> getToken(custId).map(setAuthHeader(request)).flatMap(next::exchange))
                        // Filter to send the request, and try again if it has an auth error
                        .filter((request, next) -> next.exchange(request).flatMap(clientResponse -> {
                            if (clientResponse.statusCode() == HttpStatus.UNAUTHORIZED) {
                                logger.error("Received 401 Unauthorized from linkedin for request: {} {} with X-LI-UUID header: {}", request.method(), request.url(), 
                                        clientResponse.headers().header(LINKEDIN_HEADER));
                                // Retry once if auth failed
                                return clientResponse.bodyToMono(String.class)
                                        .doOnNext(err -> logger.warn("Received 401 from linkedin; retrying once. Error body: {}", err))
                                        .then(refreshToken(custId).map(setAuthHeader(request)).flatMap(next::exchange));
                            } else if (clientResponse.statusCode().isError()) {
                                logger.error("Received error status code: {} from linkedin for request: {} {} with X-LI-UUID header: {}", clientResponse.statusCode(), request.method(), 
                                        request.url(), clientResponse.headers().header(LINKEDIN_HEADER));
                            } else {
                                logger.debug("Received status code: {} from linkedin for request: {} {}", clientResponse.statusCode(), request.method(), request.url());
                            }
                            // If not a 401, just return the response
                            return Mono.just(clientResponse);
                        })).build();
            }
    }
    
    

    您还需要记住,您需要在测试中使用注入/自动装配的 WebClient.Builder 才能使属性正常工作!

    如果您真的想推出自己的 WebClient.Builder,可以通过编程方式设置缓冲区大小(kotlin 示例):

    val webClient = WebClient.builder()
        .exchangeStrategies(
        ExchangeStrategies.builder().codecs {
            it.defaultCodecs().maxInMemorySize(1000000) // in bytes
        }.build()
    ).build()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-01
      • 2012-12-31
      • 1970-01-01
      • 2014-10-07
      • 2020-10-06
      • 2021-04-01
      • 1970-01-01
      • 2022-11-11
      相关资源
      最近更新 更多