728x90

DataBufferLimitException


Spring Webflux의 WebClient를 사용하던 중 특정 api를 호출하여 응답받는 경우 아래와 같은 예외가 발생했다.

org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144

 

원인은?

WebClient 설정에는 애플리케이션의 메모리 이슈를 방지할 수 있도록 코덱(codec)의 메모리 버퍼 사이즈 제한 값을 갖고 있다. 이 값은 기본적으로 256KB로 설정되어 있는데, 이 값을 넘어가는 경우 DataBufferLimitException 예외가 발생한다.

 

해결 방법


@Bean
fun webClient(): WebClient {
    val strategies = ExchangeStrategies.builder()
        .codecs { codecs: ClientCodecConfigurer ->
            codecs.defaultCodecs().maxInMemorySize(64 * 1024 * 1024)
        }
        .build()
    return WebClient.builder()
        .exchangeStrategies(strategies)
        .build()
}

DataBufferLimitException 예외가 발생하지 않도록 WebClient를 설정할 때 코덱(codec)의 메모리 버퍼 사이즈 제한 값을 maxInMemorySize 메서드의 파라미터로 넣어주면 된다.

만약 사이즈 제한을 두고싶지 않은 경우 메서드 파라미터로 -1을 전달하면 된다.

 

클라이언트 사이드

참고로 해당 설정의 코덱은 client side의 코덱이다.

public interface ClientCodecConfigurer extends CodecConfigurer {

	/**
	 * {@inheritDoc}
	 * <p>On the client side, built-in default also include customizations related
	 * to multipart readers and writers, as well as the decoder for SSE.
	 */
	@Override
	ClientDefaultCodecs defaultCodecs();
	
	}

 

 

서버 사이드

만약 서버사이드쪽 버퍼 사이즈를 변경하고 싶다면 WebFluxConfigurer 인터페이스를 사용하여 구성이 가능하다.

@Configuration
class WebConfig : WebFluxConfigurer {

  override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
        configurer.defaultCodecs().maxInMemorySize(10*1024*1024)
  }
}

 

 

WebClient Timeout 관련


추가적으로 WebClient의 타임 아웃 관련 설정도 알아보자. WebClient의 타임아웃을 설정하는 쉬운 방법은 기본 http 클라이언트를 사용하여 전역적으로 설정하는 것이다. 기본적으로 Reactor Netty가 사용된다.

 

Response Timeout

요청을 보낸 후 응답을 받기까지 기다리는 시간 제한이다. responseTimeout() 메서드를 통해 설정 가능하다.

val httpClient = HttpClient.create()
	.responseTimeout(Duration.ofMillis(5000))
    
return WebClient.builder()
	.clientConnector(ReactorClientHttpConnector(httpClient))
	.build()

 

Connection Timeout

커넥션 타임아웃은 클라이언트와 서버간의 연결이 이루어져야하는 시간 제한이다. option() 메서드를 통해 다양한 옵션 키값들을 설정할 수 있다. 커넥션이 이루어지지 않거나 끊어지면 ConnectTimeoutException  예외가 발생한다.

val client = HttpClient.create()
  .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
  
  
val client = HttpClient.create()
  .option(ChannelOption.SO_KEEPALIVE, true)
  .option(EpollChannelOption.TCP_KEEPIDLE, 300)
  .option(EpollChannelOption.TCP_KEEPINTVL, 60)
  .option(EpollChannelOption.TCP_KEEPCNT, 8);

 

Read and Write Timeout

read timeout은 특정 시간 내에 데이터를 읽지 못햇을 때, write timeout은 특정 시간에 쓰기 작업을 완료할 수 없을 때 발생한다.

val httpClient = HttpClient.create()
    .doOnConnected { conn: Connection ->
        conn.addHandlerLast(ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS))
            .addHandlerLast(WriteTimeoutHandler(5000, TimeUnit.MILLISECONDS))
    
}

 

그 외

이 외에도 SSL/TLS timeout, Proxy timeout, Request level의 timeout 설정 또한 가능하다.

 

참고

728x90

'spring' 카테고리의 다른 글

[spring data mongo] Query를 Type-safe 하게 작성하기 (작성 중)  (0) 2024.11.19
TestExecutionListener를 이용한 테스트 격리 방법  (1) 2024.11.05
Spring Async  (0) 2024.08.02
Spring Webclient  (0) 2024.08.02
Spring AOP  (0) 2024.08.02

+ Recent posts