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를 세팅 할 수 있으면 될거 같다.