Mientras envío un archivo, recibo una matriz de bytes. Siempre tengo un problema con webflux para recibir una matriz. el error arrojado de la siguiente manera:
org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144 at org.springframework.core.io.buffer.LimitedDataBufferList.raiseLimitException(LimitedDataBufferList.java:101) Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException¿Sabes cómo resolver eso en webflux?
Supongo que este problema se trata de agregar una nueva propiedad de configuración spring.codec.max-in-memory-size en Spring Boot. Agréguelo al archivo application.yml como:
spring: codec: max-in-memory-size: 10MBEstablezca los bytes máximos (en megabytes ) en su archivo de configuración de Spring Boot application.properties como se muestra a continuación:
spring.codec.max-in-memory-size=20MBRecibí este error para un RestController simple (publico una cadena json grande).
así es como cambié con éxito el maxInMemorySize
import org.springframework.context.annotation.Configuration; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.web.reactive.config.ResourceHandlerRegistry; import org.springframework.web.reactive.config.WebFluxConfigurer; @Configuration public class WebfluxConfig implements WebFluxConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/swagger-ui.html**") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); } @Override public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024); } }esto fue sorprendentemente difícil de encontrar
Esto funcionó para mí:
Cree un @Bean en una de sus clases de configuración o en la clase SpringBootApplication principal:
@Bean public WebClient webClient() { final int size = 16 * 1024 * 1024; final ExchangeStrategies strategies = ExchangeStrategies.builder() .codecs(codecs -> codecs.defaultCodecs().maxInMemorySize(size)) .build(); return WebClient.builder() .exchangeStrategies(strategies) .build(); } A continuación, vaya a la clase que desee en la que desee utilizar WebClient :
@Service public class TestService { @Autowired private WebClient webClient; public void test() { String out = webClient .get() .uri("/my/api/endpoint") .retrieve() .bodyToMono(String.class) .block(); System.out.println(out); } }En lugar de recuperar datos a la vez, puede transmitir:
Mono<String> string = webClient.get() .uri("end point of an API") .retrieve() .bodyToFlux(DataBuffer.class) .map(buffer -> { String string = buffer.toString(Charset.forName("UTF-8")); DataBufferUtils.release(buffer); return string; });Alternativamente, convertir a transmisión:
.map(b -> b.asInputStream(true)) .reduce(SequenceInputStream::new) .map(stream -> { // consume stream stream.close(); return string; });En la mayoría de los casos, no desea realmente agregar la transmisión, en lugar de procesarla directamente. La necesidad de cargar una gran cantidad de datos en la memoria es principalmente una señal para cambiar el enfoque a uno más reactivo. Los analizadores JSON y XML tienen interfaces de transmisión.
Otra alternativa podría ser crear un CodecCustomizer personalizado, que se aplicará tanto a WebFlux como a WebClient al mismo tiempo:
@Configuration class MyAppConfiguration { companion object { private const val MAX_MEMORY_SIZE = 50 * 1024 * 1024 // 50 MB } @Bean fun codecCustomizer(): CodecCustomizer { return CodecCustomizer { it.defaultCodecs() .maxInMemorySize(MAX_MEMORY_SIZE) } } }esto funcionó para mí
val exchangeStrategies = ExchangeStrategies.builder() .codecs { configurer: ClientCodecConfigurer -> configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024) }.build() return WebClient.builder().exchangeStrategies(exchangeStrategies).build()trabajó para mi
webTestClient.mutate().codecs(configurer -> configurer .defaultCodecs() .maxInMemorySize(16 * 1024 * 1024)).build().get() .uri("/u/r/l") .exchange() .expectStatus() .isOk()A partir de Spring Boot 2.3.0, ahora hay una propiedad de configuración dedicada para el cliente REST de Reactive Elasticsearch.
Puede usar la siguiente propiedad de configuración para establecer un límite de memoria específico para el cliente.
spring.data.elasticsearch.client.reactive.max-in-memory-size= La propiedad spring.codec.max-in-memory-size ya existente es independiente y solo afecta a otras instancias de WebClient en la aplicación.