개발계 적용

Fegin Client를 적용하여 각 요청해야하는 Core 서비스마다 Configuration을 적용하여,사용중이다.
Logger나 ReactiveOptions를 정의해서 FeginClient를 Bean으로 생성하여 사용중이다.

운영계 적용

운영계 또한 개발계 적용된 세팅값 그대로 적용하였다. 그런데 GET API 호출에서 이슈가 터졌다..

@Configuration
class MyClientConfiguration() {

    @Value("\${my.url}")
    lateinit var url: String

    @Bean
    fun MyClient(): MyClient = WebReactiveFeign
        .builder<MyClient>()
        .options(reactiveOptions())
        .addLoggerListener(loggerListener())
        .target(MoneyCollectClient::class.java, url)

    fun loggerListener(): ReactiveLoggerListener<*>? {
        return DefaultReactiveLogger(Clock.systemUTC(), LoggerFactory.getLogger(MyClient::class.java))
    }

    fun reactiveOptions(): ReactiveOptions {
        return WebReactiveOptions.Builder()
            .setReadTimeoutMillis(2000)
            .setWriteTimeoutMillis(2000)
            .setResponseTimeoutMillis(2000)
            .build()
    }
}

위 코드는 개발계 코드이다. 그런데 운영계 데이터 조회시에 DataBufferLimitException과, jsonMaxLengthException? 이 발생 하였다. 원인 분석에 들어갔다.
Webflux 세팅 문제인가?

구버전에서는 아래와 같이 설정을 하면된다고 하더라. 그런데 우리는 2.7.x 버전의 spring Boot와 webFlux가 아닌 Fegin Client를 사용하고있다.

spring:
	codec:
    	max-in-memory-size: 10MB

또는 WebFluxConfigurer 재정의 하여 사용하는 방법이 있었다.

@Configuration
class WebConfig : WebFluxConfigurer {

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

이 세팅은 모두 webFlux 세팅이지 Fegin은 아니다.

해결

WebReactiveFegin 소스 내부를 보면 Builder 함수에 WebClient.Builder를 인자로 받아서 받은 WebClient를 사용하고 있다.
이에 WebClient를 생성해서 maxInMemorySize를 설정후 FeginClient를 생성하였다.

public class WebReactiveFeign {

    public static <T> Builder<T> builder() {
        return builder(WebClient.builder());
    }

    public static <T> Builder<T> builder(WebClient.Builder webClientBuilder) {
        return new Builder<>(webClientBuilder);
    }
    .....
....
@Bean
    fun webClientBuilder(): WebClient.Builder {
        val size = 16 * 1024 * 1024
        val strategies = ExchangeStrategies.builder()
            .codecs { codecs: ClientCodecConfigurer -> codecs.defaultCodecs().maxInMemorySize(size) }
            .build()
        return WebClient.builder()
            .exchangeStrategies(strategies)
            
...

@Bean
    fun MyClient(): MyClient = WebReactiveFeign
        .builder<MyClient>(webClientBuilder)
        .options(reactiveOptions())
        .addLoggerListener(loggerListener())
        .target(MoneyCollectClient::class.java, url)

    fun loggerListener(): ReactiveLoggerListener<*>? {
        return DefaultReactiveLogger(Clock.systemUTC(), LoggerFactory.getLogger(MyClient::class.java))
    }
'''

FeginClient를 여러 곳에서 사용중이어서 Global로 WebClient Builder를 사용할 수 있도록 Bean으로 올려서 생성 하였다.

디테일한 세팅이 필요로 하면, 상황에 맞춰서 Fegin생성자에서 개별적으로 WebClient를 세팅 할 수 있으면 될거 같다.

profile
우물안 개구리에서 벗어나고 싶은 개발자

0개의 댓글