拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 如何解決 Spring Webflux DataBufferLimitException

如何解決 Spring Webflux DataBufferLimitException

白鹭 - 2022-10-19 2219 0 2

一、简介

在本教程中,我们将探讨为什么会在Spring Webflux 应用程序中看到DataBufferLimitException然后,我们将看看我们可以解决相同问题的各种方法。

2. 理解问题

在跳到解决方案之前,让我们先了解问题。

2.1。什么是DataBufferLimitException?

Spring WebFlux限制了编解码器中内存中数据的缓冲,以避免应用程序内存问题。默认情况下,它被配置为262,144 字节当这对我们的用例来说还不够时,我们将得到DataBufferLimitException

2.2.什么是Codec

spring-webspring-core模块支持通过具有反应流背压的非阻塞I/O 对更高级别对象的字节内容进行序列化和反序列化。[Codecs](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-codecs)提供了Java 序列化的替代方案。一个优点是,通常,对像不需要实现Serializable.

3.服务器端

让我们首先从服务器的角度看一下DataBufferLimitException是如何发挥作用的。

3.1。重现问题

让我们尝试将大小为390 KB 的JSON 有效负载发送到我们的Spring Webflux 服务器应用程序以创建异常。我们将使用curl命令向我们的服务器发送一个POST请求:

curl --location --request POST 'http://localhost:8080/1.0/process' \
 --header 'Content-Type: application/json' \
 --data-binary '@/tmp/390KB.json'

正如我们所见,抛出了DataBufferLimitException

org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144
 at org.springframework.core.io.buffer.LimitedDataBufferList.raiseLimitException(LimitedDataBufferList.java:99) ~[spring-core-5.3.23.jar:5.3.23]
 Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
 Error has been observed at the following site(s):
 *__checkpoint ⇢ HTTP POST "/1.0/process" [ExceptionHandlingWebHandler]

3.2.通过属性解决方案

最简单的解决方案是配置应用程序属性spring.codec.max-in-memory-size让我们将以下内容添加到我们的application.yaml文件中:

spring:
 codec:
 max-in-memory-size: 500KB

有了这个,我们现在应该能够在我们的应用程序中缓冲大于500 KB 的有效负载。

3.3.通过代码解决

或者,我们可以使用WebFluxConfigurer接口来配置相同的阈值。为此,我们将添加一个新的配置类WebFluxConfiguration:

@Configuration
 public class WebFluxConfiguration implements WebFluxConfigurer {
 @Override
 public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
 configurer.defaultCodecs().maxInMemorySize(500 * 1024);
 }
 }

这种方法也将为我们提供相同的结果。

4.客户端

现在让我们换个角度来看看客户端的行为。

4.1。重现问题

我们将尝试使用Webflux 的WebClient.让我们创建一个处理程序,以390 KB 的负载调用服务器:

public Mono<Users> fetch() {
 return webClient
 .post()
 .uri("/1.0/process")
 .body(BodyInserters.fromPublisher(readRequestBody(), Users.class))
 .exchangeToMono(clientResponse -> clientResponse.bodyToMono(Users.class));
 }

我们再次看到抛出了相同的异常,但这一次是由于webClient试图发送比允许的更大的有效负载:

org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144
 at org.springframework.core.io.buffer.LimitedDataBufferList.raiseLimitException(LimitedDataBufferList.java:99) ~[spring-core-5.3.23.jar:5.3.23]
 Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
 Error has been observed at the following site(s):
 *__checkpoint ⇢ Body from POST http://localhost:8080/1.0/process [DefaultClientResponse]
 *__checkpoint ⇢ Handler com.baeldung.[email protected]428eedd9 [DispatcherHandler]
 *__checkpoint ⇢ HTTP POST "/1.0/trigger" [ExceptionHandlingWebHandler]

4.2.通过属性解决方案

同样,最简单的解决方案是配置应用程序属性spring.codec.max-in-memory-size让我们将以下内容添加到我们的application.yaml文件中:

spring:
 codec:
 max-in-memory-size: 500KB

有了这个,我们现在应该能够从我们的应用程序发送大于500 KB 的有效负载。值得注意的是,此配置应用于整个应用程序,这意味着所有Web 客户端和服务器本身。

因此,如果我们只想为特定的Web 客户端配置此限制,那么这将不是一个理想的解决方案。此外,这种方法有一个警告用于创建WebClients的构建器必须由Spring 自动连接,如下所示:

@Bean("webClient")
 public WebClient getSelfWebClient(WebClient.Builder builder) {
 return builder.baseUrl(host).build();
 }

4.3.通过代码解决

我们还有一种编程方式来配置Web 客户端以实现这一目标。让我们使用以下配置创建一个WebClient

@Bean("progWebClient")
 public WebClient getProgSelfWebClient() {
 return WebClient
 .builder()
 .baseUrl(host)
 .exchangeStrategies(ExchangeStrategies

 .builder()

 .codecs(codecs -> codecs
 .defaultCodecs()
 .maxInMemorySize(500 * 1024))

 .build())
 .build();
 }

有了这个,我们现在应该能够使用我们的Web 客户端成功发送大于500 KB 的有效负载。

5. 结论

在本文中,我们了解了DataBufferLimitException是什么,并研究了如何在服务器端和客户端修复它们。我们研究了两种方法,首先是基于属性配置,其次是编程。我们希望这个例外不会再给您带来麻烦。



标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *